Why isn't a final variable always a constant expression?
In the below code:
final int a;
a=2;
byte b=a; // error: possible loss of precision
Why do I get this error? Isn't a
final variable compile time constant expression and hence implicitly narrowed to byte during the assignment?
In other words isn't the above code equivalent to:
final int a=2;
byte b=a;
Solution 1:
From the JLS
A blank
final
is afinal
variable whose declaration lacks an initializer.A constant variable is a
final
variable of primitive type or typeString
that is initialized with a constant expression (§15.28).
Your variable
final int a;
is a blank final
variable. It lacks an initializer. The second paragraph doesn't apply to it because it is not initialized at declaration. It therefore isn't a constant expression.
This applies to fields as well.
Solution 2:
The compiler isn't that smart.
We can tell that the value will always be 2. But what if we had something like this?
class ABC{
final int a;
public ABC(){
if(Math.random() < .5){
a = 2;
}
else{
a = 12345;
}
byte b = a;
}
}
The compiler is not smart enough to tell these two cases apart, so it gives you an error instead.
Solution 3:
As final variables can be delayed initialized and the compiler cannot determine for b that it has a value in the case branch.