As far as I know, Java deals with constant variables §4.12.4 by constant folding in compile time. I’ve tried my best, but I couldn’t find its description from JLS. Could anybody tell me where I could find official description of the constant folding process for Java 11?
Advertisement
Answer
The specification does not use the term Constant Folding.
It has the definition of Constant Expressions
A 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:[…]
Constant expressions of type
String
are always “interned” so as to share unique instances, using the methodString.intern
.A 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.
Constant expressions are used as
case
labels inswitch
statements (§14.11) and have a special significance in assignment contexts (§5.2) and the initialization of a class or interface (§12.4.2). They may also govern the ability of awhile
,do
, orfor
statement to complete normally (§14.21), and the type of a conditional operator? :
with numeric operands.
The last part does already point out where precalculation of constant expressions is mandatory. When it comes to case
labels, the compiler is required to report duplicates, hence, it must calculate the values at compile-time. When calculating loops, it must calculate constant boolean expressions to determine code reachability.
Likewise, initializers need precalculation to determine the correctness. E.g. short s = 'a' * 2;
is a correct declaration, but short s = Short.MAX_VALUE + 1;
is not.
A well known use case of constant expressions is the initializer of constant variables. When reading a constant variable, the constant value will be used instead of reading the variable, compare with the Q&A “Does the JLS require inlining of final String constants?”
But this does not imply that “constant folding” is mandatory. In theory, a conforming implementation still could perform the calculation of the constant expression as written in the variable initializer at every place where the variable is used. In practice, the bytecode format leads to a constant folding behavior. The ConstantValue
attribute which is used to record the value of a constant variable in bytecode can only hold a precalculated value. When compiling against an already compiled class file, the original expression of a constant variable is not available to the compiler. It can only use the precalculated value.
Likewise, compiling a switch
instruction is normally done using either, the tableswitch
or the lookupswitch
instruction, both requiring precalculated int
values for the case
labels. A compiler would have to go great length to implement a different strategy.
Also, the compiled format for annotation values can only hold precalculated expressions.