Question

Is doing:

String a = new String();
String b = a;

and doing:

String a = new String();
String b = a.intern();

is the same ?

Actually, the reference are all the same if I test:

String a = new String("te");
String b = a.intern();
String c = a;
String d = "t" + "e";
System.out.print(a.equals(b));
System.out.print(b.equals(c));
System.out.print(a.equals(d));

Cause the String will ever be in the String pool ?

Was it helpful?

Solution

Your equals tests aren't checking for references - they're checking for string equality. You should be using == to check the references for identity. Effectively, you're making the common rookie Java mistake in reverse - usually people use == when they should be using equals. In this particular case, all of those will print false, because there are two String objects involved (the string from the constant pool, and the new string created in the first line). If we call these #1 and #2 respectively, we end up with:

a = #2 // Explicit call to string constructor
b = #1 // intern will return reference to constant pool instance
c = #2 // Direct assignment
d = #1 // Equivalent string constant, so reference to constant pool instance

However, you may find this interesting:

String a = "te";
String b = a.intern();
String c = "t" + "e";
System.out.println(a == b); // true
System.out.println(a == c); // true

"te" and "t" + "e" are equal constant string expressions, so end up as references to a single string, and calling intern on a string already in the literal pool won't have any effect.

OTHER TIPS

To start off: "t" + "e" is a String literal, because it will be optimised by the compiler. This string literal is also used in this line:

String a = new String("te");

Now, the String(String) constructor makes a physical copy of the String. So, this means that a and d are not the same object.

Then: String.equals(String) compares two Strings. It says if the content was equal and not the object. This means you might have two different String objects which have the same sequence of characters, which will make the String.equals(String) return true.

String.intern() puts the String in the String pool, if it isn't yet in it. But this method can't change the object itself. So this code example will print false:

String literal = "lit";
String nonLiteral = "abclit".substring(3); // equals "lit"
nonLiteral.intern(); // "lit" was already in the String pool
                     // but `nonLiteral` is still `nonLiteral`
System.out.println(literal == nonLiteral); // false

However if you would do this: it will return true:

String literal = "lit";
String nonLiteral = "abclit".substring(3); // equals "lit"
nonLiteral = nonLiteral.intern(); // "lit" was already in the String pool and
                                  // it will return the object `literal`.
                                  // Now the value is replaced.
System.out.println(literal == nonLiteral); // true

If that string value has already been interned from a different String instance, intern() will return the earlier instance.

Using equals doesn't test the equality of the references. It tests the equality of the contents of the String. You need to use == to test the equality of the references.

To answer your question, no, it's not the same. The first snippet assigns two references (a and b) to the same String. The second one creates a String, assigns it to a, then interns the String and assigns the String that the intern pool returns to b. a and b could thus refer to two different String instances (and certainly will, because the empty String is in the pool for sure, thus intern() will not return the STring referred to by a, but will returned the pooled empty String)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top