Compile-time constants and variables

JavaPerformanceConstantsFinalCompile Time-Constant

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

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 - Java

The JLS makes the following distinctions between final variables and constants:

###final variables

> A variable can be declared final. A final variable may only be > assigned 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 (§16 (Definite Assignment)). > > Once a final variable has been assigned, it always contains the same > value. If a final 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 a final 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 a final variable whose declaration lacks an > initializer.

###constants

> A constant variable is a final variable of primitive type or type > String 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 - Java

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 - Java

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 - Java

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 6 - Java

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;
}

Solution 7 - Java

private final int x = getX(); Will be called the first time your object is declared. The performance "drop" will depend on getX() but that's not the kind of things to create some bottleneck.

Solution 8 - Java

Simply speaking while compilation the compiler replaces the reference with the actual value specified, instead of using the reference parameter.

public static void main(String[] args) {
final int x = 5;
}

ie. while compilation the complier take the initialised value of 5 directly for compliation than using the reference variable 'x';

Please check this explanation

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAllTooSirView Question on Stackoverflow
Solution 1 - JavamsiView Answer on Stackoverflow
Solution 2 - Javauser9514304View Answer on Stackoverflow
Solution 3 - JavaCode CompleteView Answer on Stackoverflow
Solution 4 - JavaThomasView Answer on Stackoverflow
Solution 5 - JavamegathorView Answer on Stackoverflow
Solution 6 - Javamatrix2323View Answer on Stackoverflow
Solution 7 - JavaUmNyobeView Answer on Stackoverflow
Solution 8 - JavaNikhil SebanView Answer on Stackoverflow