1

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.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Nizam
  • 573
  • 1
  • 5
  • 12
  • You can possibly get a compile-time error there when those two lines are separated by some other statement trying to access `x`. Otherwise not sure what doesn't work for you! – Naman Dec 22 '18 at 17:08
  • I think they also aimed at a not too complicated set of rules. I can’t imagine a manageable rule that would cover your second snippet without giving trouble elsewhere. Where to draw the limit? – Ole V.V. Dec 22 '18 at 17:21
  • I'm voting to close this question as off-topic because answers cannot be but guesswork (and thought-reading at best), – Ole V.V. Dec 22 '18 at 17:22
  • 1
    run the code final int a = 1; final int b; b = 2; switch(1) { case a : //OK case b : //compile error – Nizam Dec 22 '18 at 17:26
  • If any variables is declared as final, which means it can initialize only once and that should happens at the time of declaration @Nizam – Ryuzaki L Dec 22 '18 at 17:30

2 Answers2

2

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.

forpas
  • 160,666
  • 10
  • 38
  • 76
  • Much better explanation, But what I observe is there might be a slight difference in back end running but on front end their behavior will be same i.e on console they both will print 5 and can never ever be reassigned.@forpas – Nizam Jan 01 '19 at 11:54
  • @Nizam *can never ever be reassigned* of course because they are declared `final`. The difference (as you can see by the bytecode) is that in the 1st case the value of `x` is replacing at compile time every reference to `x`. – forpas Jan 01 '19 at 12:12
0

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.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243