Compile-time constants and variables

42,597

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

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 3

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 4

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.

Solution 5

Just keep in mind that in the following code, x is not compile time constant:

public static void main(String[] args) {
     final int x;
     x= 5;
}
Share:
42,597
AllTooSir
Author by

AllTooSir

Updated on July 09, 2020

Comments

  • AllTooSir
    AllTooSir almost 4 years

    The Java language documentation says:

    If a primitive type or a string is defined as a constant and the value is known at compile time, the compiler replaces the constant name everywhere in the code with its value. This is called a compile-time constant.

    My understanding is if we have a piece of code:

    private final int x = 10;
    

    Then, the compiler will replace every occurrence of x in the code with literal 10.


    But suppose the constant is initialized at run-time:

    private final int x = getX(); // here getX() returns an integer value at run-time.
    

    Will there be any performance drop (howsoever negligible it may be) compared to the compile-time constant?


    Another question is whether the below line of code:

    private int y = 10; // here y is not final
    

    is treated in same way as compile-time constant by the compiler?


    Finally, what I understand from the answers are:

    1. final static means compile-time constant
    2. just final means it's a constant but is initialized at run-time
    3. just static means initialized at run-time
    4. without final is a variable and wouldn't be treated as constant.

    Is my understanding correct?