0

I know that "==" compare reference and the a java String is immutable and use a string pool cache but I'm still confusing on this example :

 final String fName = "James";
        String lName = "Gosling";
        String name1 = fName + lName;
        String name2 = fName + "Gosling";
        String name3 = "James" + "Gosling";
       System.out.println(name1 == name2);  // 1
        System.out.println(name2 == name3);

This gave me as results :

false
true

I still confused why System.out.println(name1 == name2); give me a false as I know the both values should be cached in the string pool ?

e2rabi
  • 4,728
  • 9
  • 42
  • 69
  • I know that ! I'm trying to understand this example – e2rabi Dec 29 '19 at 13:55
  • You got `false` because `name1` and `name2` are two different objects. – Sudhir Ojha Dec 29 '19 at 13:56
  • 1
    Concatenation of compile-time constants is done at compilation time, so when you have `"a"+"b"` compiler will change it into `"ab"` and that string will be interned. Same rule applies to `final String str1 = "a"; final String str2 = "b";` for which `str1+str2 == "ab"` will also be `true`. – Pshemo Dec 29 '19 at 13:59
  • Can u plz explain why the both are differents objects ? – e2rabi Dec 29 '19 at 13:59
  • Which objects do you mean? – Pshemo Dec 29 '19 at 14:02
  • your response is helpful , I mean objects name1 and name2 – e2rabi Dec 29 '19 at 14:04
  • Possibly related: [Comparing strings with == which are declared final in Java](https://stackoverflow.com/q/19418427) – Pshemo Dec 29 '19 at 14:05
  • If you want to see this in a different way print the `System.identityHashCode(String)` for your names and see the hashCodes. – WJS Dec 31 '19 at 00:40

2 Answers2

3

Since fName is final and initialized with a literal String, it's a constant expression.

So the instruction

String name2 = fName + "Gosling"

is compiled to

String name2 = "James" + "Gosling"

which is compiled to

String name2 = "JamesGosling"

So, in the bytecode, you have the equivalent of

String name2 = "JamesGosling";
String name3 = "JamesGosling";

So both name2 and name3 reference the same literal String, which is interned.

On the other hand, lName is not final, and is thus not a constant expression, and the concatenation happens at runtime rather than at compile time. So the concatenation creates a new, non-interned String.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

Creating two strings with same string values does not guarantee they are both from the String Pool. You need to call s.intern() to ensure you get a String that has both same value and memory address from String Pool.

There is a good chance the concatenation is causing the String to be read as String Object instead of a String literal. This is due to the compiler not knowing if fName + lName will result to a literal or not. If it's a String literal, it goes to the String Pool. If it's a String Object, it is is not guaranteed to go to the String Pool and be treated like any other Object.