Nizam
Nizam

Reputation: 623

Compile Time Constant

I understood what a compile time constant rule is from Compile-time constants and variables.

  1. declared as final
  2. have a primitive or String type
  3. initialized at the same time as the declaration
  4. initialized with constant expression

final int x = 5;

But I fail to understand why below code doesn't:

final int x;
x = 5;

The only difference is of third point above. How initialization on different line instead of same line makes a difference.

Upvotes: 1

Views: 1134

Answers (2)

Andy Turner
Andy Turner

Reputation: 140299

From JLS Sec 4.12.4:

constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.28).

If the variable is declared without being initialized, it is by definition not a constant variable, even if the value you eventually assign to it is a constant expression.

Upvotes: 0

forpas
forpas

Reputation: 164064

Case 1 final int x = 5;

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

The bytecode generated is:

  public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 3 L0
    ICONST_5
    ISTORE 1
   L1
    LINENUMBER 4 L1
    RETURN
   L2
    LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
    LOCALVARIABLE x I L1 L2 1
    MAXSTACK = 1
    MAXLOCALS = 2

Case 2 final int x; x = 5;

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

The bytecode generated is:

  public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 4 L0
    ICONST_5
    ISTORE 1
   L1
    LINENUMBER 5 L1
    RETURN
   L2
    LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
    LOCALVARIABLE x I L1 L2 1
    MAXSTACK = 1
    MAXLOCALS = 2

As you can see there is no difference between the 2 cases, except for the line numbers.

In fact in an ide such as InteliJ you will see the prompt (as a light bulb) to join the 2 lines of case 2, to 1 line like case 1.

If you read all the answers and comments in the link you provided,
you will be more confused than wiser about this.
It's all about terminology and in this case not documented terminology.

This is an excerpt of one of the answers in that link:

The JLS does not contain the phrase compile-time constant.
However, programmers often use the terms compile-time constant and constant interchangeably.

Now for the case of how the compiler uses the 2 cases.
If you add this line at the end of both methods:

System.out.println(x);


the bytecode generated is:
for case 1

GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ICONST_5
INVOKEVIRTUAL java/io/PrintStream.println (I)V

and for case 2

GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ILOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (I)V

There is a difference in the 2nd case: ILOAD 1 instead of ICONST_5.
Meaning in the 1st case x was replaced by 5 and in the 2nd case it was not and the value of x was recalled (loaded) to execute the statement.

Upvotes: 2

Related Questions