Must all final variables be compile time constants?
The final variables are not necessary compile time constants.
For example, the following code shows that variable k is a final variable but not a compile time constant:
public class Program {
void unflow(boolean flag) {
final int k;
if (flag) {
k = 3;
System.out.println(k);
}
else {
k = 4;
System.out.println(k);
}
}
....
}
A final variable may only be assigned a value to once. It is a compile time error if a final variable is assigned to unless it is definitely unassigned immediately prior to the assignment.
A blank final is a final variable whose declaration lacks an initializer. Once a final variable has been assigned, it always contains the same value. (4.12.4 final Variables)
For a final variable to be a compile time constant, it must have an initializer and that initializer is a compile-time constant expression which may contain forward references to other compile-time constants
What is a compile-time constant expression? The following is the definition from Java Language Specification 3rd Edition (15.28 Constant Expression):
A compile-time constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:
-
Literals of primitive type and literals of type String (3.10.5)
-
Casts to primitive types and casts to type String
-
The unary operators +, -, ~, and ! (but not ++ or --)
-
The multiplicities operators *, /, and %
-
The additive operators + and -
-
The shift operators <<, >>, and >>>
-
The relational operators <, <=, >, and >= (but not instanceof)
-
The equality operators == and !=
-
The bitwise and logical operators &, ^, and |
-
The conditional-and operator && and the conditional-or operator ||
-
The ternary conditional operator ? :
-
Parenthesized expressions whose contained expression is a constant expression.
-
Simple names that refer to constant variables (4.12.4).
-
Qualified names of the form TypeName . Identifier that refer to constant variables (4.12.4).
Compile-time constant expressions are used in case labels in switch statements (14.11) and have a special significance for assignment conversion (5.2). Compile-time constants of type String are always "interned" so as to share unique instances, using the method String.intern.
A compile-time constant expression is always treated as FP-strict (15.4), even if it occurs in a context where a non-constant expression would not be considered to be FP-strict.