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?
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
Stringthat does not complete abruptly and is composed using only the following:
Constant expressions of type
Stringare always “interned” so as to share unique instances, using the method
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
switchstatements (§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 a
forstatement 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.