With your first example:
String y = "Hey";
Java automatically interns string literals such as this (JLS section 3.10.5):
Moreover, a string literal always refers to the same instance of class
String. This is because string literals - or, more generally, strings
that are the values of constant expressions (§15.28) - are "interned"
so as to share unique instances, using the method String.intern.
So when you call x.intern()
, you get the interned copy of "Hey"
, so they are the same object and ==
returns true
.
But in the second example, b.intern()
is a method call that is evaluated at runtime, and Java's concatenation operator will return a new String
(not interned), which is a different object than the string literal "hey"
(interned already), so ==
returns false
(different objects).
EDIT
To clear up what happens with the string concatenation, turn to JLS Section 15.18.1:
The result of string concatenation is a reference to a String object
that is the concatenation of the two operand strings. The characters
of the left-hand operand precede the characters of the right-hand
operand in the newly created string.
The String object is newly created (§12.5) unless the expression is a
compile-time constant expression (§15.28).
But, b.intern() + "ey";
is not a compile-time constant expression, so the resultant String
object has not been interned, and ==
will detect that it's a different object than the interned "hey"
.