A String
literal is always automatically interned the first time it appears. The String
literals you have in your code are "11" and "2".
On the other hand, the String
created as a result of String
concatenation is not automatically interned.
String a = new String("11"); // interns the String literal "11", and creates a
// different String instance referenced by a
a.intern(); // doesn't add a to the String pool, since "11" is already in
// the String pool
String b = "11"; // "11" returns the canonical instance already in the pool,
// which is != a
Hence a != b
.
String c = new String("2") + new String("2"); // interns the String "2", creates 2
// more Strings having the same value,
// and creates an additional String
// whose value is "22", which is not
// interned yet
c.intern(); // c is added to the String pool as the canonical instance whose value
// is "22"
String d = "22"; // "22" returns the canonical instance already in the pool,
// which is == c
Hence c == d
.
All of the above follows from the Javadoc of intern
:
Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.