14

Are the below two pieces of code the same?

String foo = "foo";
String foo = new String("foo").intern();
Kshitij
  • 361
  • 1
  • 9
foo
  • 143
  • 1
  • 4

5 Answers5

16

They have the same end result, but they are not the same (they'll produce different bytecode; the new String("foo").intern() version actually goes through those steps, producing a new string object, then interning it).

Two relevant quotes from String#intern:

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.

All literal strings and string-valued constant expressions are interned.

So the end result is the same: A variable referencing the interned string "foo".

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • In this case, new String("foo").intern();, the newly created string object is not added to the heap right? – foo Apr 25 '11 at 10:18
  • 3
    @foo: It probably is, but it's immediately available for reclamation again by the GC, as by the end of the expression there are no outstanding references to it. And I expect an optimizing JVM (like Sun/Oracle's HotSpot) optimizes the `new String("foo").intern()` away on the first pass anyway, once it's noted that there are no side-effects to calling the constructor. Or it may not because barring this being in a tight loop, it doesn't meet the threshold of being worth it. – T.J. Crowder Apr 25 '11 at 10:23
  • Thanks for that. I was wondering why would anyone ever use new String("foo") idiom to initialize strings when if I do it that way, I create two objects, one on the heap and the other in the pool. Is there any advantage of using new String("foo") that I am missing other than an uniform pattern to initialize all objects in Java? – foo Apr 25 '11 at 10:29
  • 1
    @foo: The only advantage I can think of is if you *don't* use `intern`, you know that the string *reference* is unique even if the string contents are not. Not many use-cases for that, I wouldn't think, but since `new String("foo") != "foo"` by definition, it could be handy on some occasions. Not many, though, I wouldn't have thought. – T.J. Crowder Apr 25 '11 at 10:40
4

public String intern()

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.

So I believe the answer is yes, although the second method will have to search through the pool.

EDIT

As sugegsted by T.J. Crowder

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.

All literal strings and string-valued constant expressions are interned.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • 1
    I think the more relevant two quotes are: *"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."* and *"All literal strings and string-valued constant expressions are interned."* – T.J. Crowder Apr 25 '11 at 09:55
  • Now this should be per JVM basis right? So if i have a cluster than it will behave differently. – Pushkar Apr 25 '11 at 10:30
3

The first one i.e.

    String foo = "foo";

in this line, we are creating a String using String literals. That means the string is automatically saved in String Constant pool.

In the 2nd one , i.e. -

    String foo = new String("foo").intern();

Here we are creating a String using new String() & then manually saving it to the String constant pool. If we didn't have mentiones intern() , it would not have saved in the String constant pool.

For more clarification, please refer to this link -

http://javacodingtutorial.blogspot.com/2013/12/comparing-string-objects-intern-other.html

Srijani Ghosh
  • 3,935
  • 7
  • 37
  • 68
  • 2
    This answer can't be more wrong. To say that the second snippet won't have the String in the pool without calling `intern()` is obviously wrong, because it ___still___ uses the literal `"foo"`. The effect of `intern` is in this context, that the call to the String constructor doesn't matter anymore and `foo` refers to the literal version `"foo"` and not the newly constructed one. – Tom Jan 07 '18 at 17:31
0

Yes, they are same. Basically intern() returns a representation of a string that is unique across the VM. This means you can use == instead of .equals() to compare the strings, saving on performance.

lobster1234
  • 7,679
  • 26
  • 30
0

Explicitly constructing a new String object initialized to a literal produces a non-interned String. (Invoking intern() on this String would return a reference to the String from the intern table.)

Taken from : http://javatechniques.com/public/java/docs/basics/string-equality.html

Favonius
  • 13,959
  • 3
  • 55
  • 95