I have two programs which are almost identical. The first compiles, the second not. Why?
I am assigning an int
variable to a byte
variable.
This one compiles:
class Example {
public static void main(String args[]) {
final int x = 127; // directly initialized
byte b;
b = x;
System.out.println(b);
}
}
This one does not compile:
class Example {
public static void main(String args[]) {
final int x;
x = 127; // assigned later
byte b;
b = x;
System.out.println(b);
}
}
The compiler says incompatible types at b = x;
. But shouldn't the same apply to the first version as well?
This one is obscure. Really obscure.
The first version works because the JLS says in section §5.2 that you can assign an int
value to a byte
variable if the value is the result of a constant expression AND the int value is in the range -128 to +127. A constant variable is a constant expression, and final int x = 127;
declares a constant variable.
The second version doesn't work because final int x;
doesn't declare a constant variable. The JLS says the following in section §4.12.4:
A constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.28).
In the second version, the final variable has a blank initializer and is then assigned later. The upshot is that the rule in §5.2 that allows narrowing of primitive constants in an assignment is not allowed.
Why couldn't final int x;
be treated as a compile time constant?
Consider this:
final int x;
if (something) {
x = 127;
} else {
x = 1023;
}
byte b = x;
Should the initialization of b
be allowed, or will it be a "lossy" conversion? It depends on the value of something
.
Hypothetically, a compiler could decide in some variants of the example above that all possible values of x
would be OK, but the added complexity in the compiler and the language specification is not justifiable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With