2
public class Example {

public static void main(String[] args) {

    String a = "abc"; // Line 5
    String b = a + "d"; // Line 6
    String c = "abc"+ "d"; // Line 7
    String d = "abcd"; //Line 8

    System.out.println(b==c); //Line 10 
    System.out.println(c==d); //Line 11
}
}

Output:
false
true

If we see Ref. variable 'b' is pointing "abcd" string object and Ref. variable 'c' is also pointing same String object i.e "abcd" but when we check equality using == (double equal operator) operator it prints false at Line 10. But if we make Ref. variable 'a' as final then it prints true at Line 10

So i am bit confuse. Can any one tell me what is happening behind it?

Kayaman
  • 72,141
  • 5
  • 83
  • 121

2 Answers2

3

Making a final allows the compiler to interpret b = a + "d"; exactly like c = "abc"+ "d";, since the value of a cannot change.

In this case the compiler could easily see that a isn't being changed, but javac doesn't do very complicated code analysis, so you need to help it by making a final in order for the compiler to optimize at compile time.

Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • As we know that we can't change String object once it is created because by nature String is immutable in java. So why we need to make String object as final – Gaurav Priyadarshi Apr 04 '18 at 16:10
  • 1
    @GauravPriyadarshi a `String` object is immutable, but the variable `a` can be changed. Objects can't be `final`, variables referring to them can be. – Kayaman Apr 04 '18 at 16:27
3

For what it's worth it, here is a comparison of the bytecodes. The left one shows the result of compiling it without the final modifier, and the right one is with the final modifier:

 0: ldc           #2      // String abc    |     0: ldc           #2      // String abcd
 2: astore_1                               |     2: astore_2
 3: new           #3      // class ...     |
 6: dup                                    |
 7: invokespecial #4      // Method ...    |
10: aload_1                                |
11: invokevirtual #5      // Method ...    |
14: ldc           #6      // String d      |
16: invokevirtual #5      // Method ...    |
19: invokevirtual #7      // Method ...    |
22: astore_2                               |
23: ldc           #8      // String abcd   |     3: ldc           #2      // String abcd
25: astore_3                               |     5: astore_3
26: ldc           #8      // String abcd   |     6: ldc           #2      // String abcd
28: astore        4                        |     8: astore        4
30: getstatic     #9      // Field ...     |    10: getstatic     #3      // Field ...
33: aload_2                                |    13: aload_2
34: aload_3                                |    14: aload_3
35: if_acmpne     42                       |    15: if_acmpne     22
38: iconst_1                               |    18: iconst_1
39: goto          43                       |    19: goto          23
42: iconst_0                               |    22: iconst_0
43: invokevirtual #10     // Method ...    |    23: invokevirtual #4      // Method ...
46: getstatic     #9      // Field ...     |    26: getstatic     #3      // Field ...
49: aload_3                                |    29: aload_3
50: aload         4                        |    30: aload         4
52: if_acmpne     59                       |    32: if_acmpne     39
55: iconst_1                               |    35: iconst_1
56: goto          60                       |    36: goto          40
59: iconst_0                               |    39: iconst_0
60: invokevirtual #10     // Method ...    |    40: invokevirtual #4      // Method ...
63: return                                 |    43: return

One can see that the bytecodes are basically the same, except for the beginning: Here, the version that does not have the final modifier loads the strings "abc" and "d" and assembles them using some StringBuilder#append calls.

So this basically confirms what Kayaman said in his answer : The string can be assembled into "abcd" beforehand, by the compiler, if the final modifier is added.

Marco13
  • 53,703
  • 9
  • 80
  • 159