Compile-time constants and variables
Solution 1:
Compile time constant must be:
- declared final
- primitive or String
- initialized within declaration
- initialized with constant expression
So private final int x = getX();
is not constant.
To the second question private int y = 10;
is not constant (non-final in this case), so optimizer cannot be sure that the value would not change in the future. So it cannot optimize it as good as constant value. The answer is: No, it is not treated the same way as compile time constant.
Solution 2:
The JLS makes the following distinctions between final
variables and constants:
final
variables
A variable can be declared
final
. Afinal
variable may only be assigned to once. It is a compile-time error if afinal
variable is assigned to unless it is definitely unassigned immediately prior to the assignment (§16 (Definite Assignment)).Once a
final
variable has been assigned, it always contains the same value. If afinal
variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object. This applies also to arrays, because arrays are objects; if afinal
variable holds a reference to an array, then the components of the array may be changed by operations on the array, but the variable will always refer to the same array.A blank
final
is afinal
variable whose declaration lacks an initializer.
constants
A constant variable is a
final
variable of primitive type or typeString
that is initialized with a constant expression (§15.28).
From this definition, we can discern that a constant must be:
- declared
final
- of primitive type or type
String
- initialized within its declaration (not a blank
final
) - initialized with a constant expression
What about compile-time constants?
The JLS does not contain the phrase compile-time constant. However, programmers often use the terms compile-time constant and constant interchangeably.
If a final
variable does not meet the criteria outlined above to be considered a constant, it should technically be referred to as a final
variable.
Solution 3:
According to JLS, there is no requirement that "constant variable" should be static.
So "constant variable" maybe static or non-static (instance variable).
But JLS imposes some other requirements for a variable to be a "constant variable" (besides being just final):
- being only String or primitive
- initialized inline only, because it is final, and blank final is not allowed
- initialized with "constant expression" = "compile-time constant expression" (see JLS quote below)
4.12.4. final Variables (JLS)
A constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.28).
15.28. Constant Expressions
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.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)
Casts to primitive types and casts to type String (§15.16)
The unary operators +, -, ~, and ! (but not ++ or --) (§15.15.3, §15.15.4, §15.15.5, §15.15.6)
The multiplicative operators *, /, and % (§15.17)
The additive operators + and - (§15.18)
The shift operators <<, >>, and >>> (§15.19)
The relational operators <, <=, >, and >= (but not instanceof) (§15.20)
The equality operators == and != (§15.21)
The bitwise and logical operators &, ^, and | (§15.22)
The conditional-and operator && and the conditional-or operator || (§15.23, §15.24)
The ternary conditional operator ? : (§15.25)
Parenthesized expressions (§15.8.5) whose contained expression is a constant expression.
Simple names (§6.5.6.1) that refer to constant variables (§4.12.4).
Qualified names (§6.5.6.2) of the form TypeName . Identifier that refer to constant variables (§4.12.4).
Solution 4:
There might be a really small performance drop on some machines for private final int x = getX();
since that would involve at least one method call (besides the fact that this isn't a compile-time constant) but as you said, it would be negligible so why bother?
As for the second question: y
isn't final and thus is not a compile time constant, since it might change at runtime.
Solution 5:
The final
keyword means that a variable will be initialized once and only once. A real constant need to be declared static
as well.
So, none of your examples are treated as constants by the compiler. Nevertheless, the final keyword tells you (and to the compiler) that your variables will be initialized once only (in the constructor or literally).
If you need their values assigned at compile time your fields must be static.
Performance is not really that affected, but have in mind that primitive types are immutable, once you have created one it will hold that value in memory until the garbage collector removes it.
So, if you have a variable y = 1;
and then you change it to y = 2;
in memory the JVM will have both values, but your variable will "point" to the latter.
private int y = 10; // here y is not final
is treated in same way as compile time constant by the compiler ?
No. This is an instance variable, created, initialized an used at runtime.