0

I understand String's intern method.

String s1 = "Hello";             
String s4 = new String("Hello").intern();  

Output of (s1 == s4) will be true, it would be false had we not used intern.

My question is on executing the above two statements, how many objects will be created?? One or two? Will new operator creates one more object?

I understand that String s4 = new String("Hello") will create two objects, but got confused with using intern with it.

C Snover
  • 17,908
  • 5
  • 29
  • 39
Anand
  • 20,708
  • 48
  • 131
  • 198
  • I take it back, the `.intern()` at the end of your second line makes it different from [this](http://stackoverflow.com/questions/10045147/how-many-objects-are-being-created?rq=1), [this](http://stackoverflow.com/questions/1881922/questions-about-javas-string-pool), and [this](http://stackoverflow.com/questions/11180866/how-many-string-objects-will-be-created-in-memory?lq=1). – T.J. Crowder Sep 20 '14 at 12:43
  • It's a bit of a trick question, since the number could be 2, 3, or 4. – Hot Licks Sep 20 '14 at 12:44
  • 1
    (But this identical question HAS been asked before. It's apparently a standard interview question or some such. And a stupid one (as it seems many interview questions are).) – Hot Licks Sep 20 '14 at 12:45

3 Answers3

1

It will be two

one for

String s1 = "Hello"; 

another for

String s4 = new String("Hello")
M Sach
  • 33,416
  • 76
  • 221
  • 314
  • then, what's the use of intern in the above? – Anand Sep 20 '14 at 12:36
  • with intern, it will look into permgen space for string literal "Hello". So here you not achieving anything with intern – M Sach Sep 20 '14 at 12:47
  • @Anand - Intern causes the original "Hello" instance to be returned. – Hot Licks Sep 20 '14 at 12:47
  • @Hot Licks- so what's the benefit? – Anand Sep 20 '14 at 12:55
  • 1
    @Anand a case where you would like to refer intern is to refer the same string object like in case hash based data structure key. – M Sach Sep 20 '14 at 13:34
  • @Anand - I suspect there are a number of developers in the Oracle Java shop who wish that `intern` had never been invented. It allows you to do string compares with `==`, but it's a PITA to implement and it can wreck havoc on heap management. – Hot Licks Sep 20 '14 at 18:10
  • Of course, there is no need to use `intern` to use String keys in a hashtable. The main benefit of `intern` is that it guarantees that two identical string literals will always be the same object, which has some internal benefits. – Hot Licks Sep 21 '14 at 11:56
0

You should use intern when you need to optimize your code, because comparing string by reference is faster.

As for your statement, only two object will be created.

Note that too much use of intern may cause to a memory exception as they are stored in the PermGen which is normally small, so make sure you configure correctly your JVM.

Jean-François Savard
  • 20,626
  • 7
  • 49
  • 76
  • `intern` is only useful for *repeated* compares of the same values, since the `intern` operation itself is quite expensive. – Hot Licks Sep 20 '14 at 12:49
  • 1
    In 15 years of programming in Java I've never seen a case where intern() was necessary for optimization. However, I have seen a few cases where it was used needlessly and/or made performance actually worse. – Thomas Stets Sep 20 '14 at 13:00
0

...how many objects will be created?? One or two?

Two. But only one of them is kept. The other is immediately eligible for garbage collection.

Will new operator creates one more object?

Yes. Briefly. But then you call its .intern method and save the result. Its .intern method will return the same interned string that s1 points to, and so the object created via new is (again) immediately eligible for GC.

We can see this if we look at the bytecode:

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String Hello
       2: astore_1
       3: new           #3                  // class java/lang/String
       6: dup           
       7: ldc           #2                  // String Hello
       9: invokespecial #4                  // Method java/lang/String."":(Ljava/lang/String;)V
      12: invokevirtual #5                  // Method java/lang/String.intern:()Ljava/lang/String;
      15: astore_2      
      16: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
      19: aload_2       
      20: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      23: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
      26: aload_1       
      27: aload_2       
      28: if_acmpne     35
      31: iconst_1      
      32: goto          36
      35: iconst_0      
      36: invokevirtual #8                  // Method java/io/PrintStream.println:(Z)V
      39: return        

3-9 create a new String object from "Hello", leaving its reference on the stack, and then we immediately call intern (which pops the reference to the new string from the stack), and store the return value of intern in s4. So the object temporarily created is no longer referenced.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks..but what are we achieving by using intern? – Anand Sep 20 '14 at 12:47
  • 1
    @Anand: The idiom `new String(someString).intern()` used to be used when `someString` was a substring of a larger string and you were going to hold onto it for a long time. For most of Java's lifetime, if you did `someString = someBigString.substring(10, 20)`, `someString` and `someBigString` referred to the same character array (with all of the characters for `someBigString`). So if you released `someBigString`, it was a memory leak -- `someString` had a reference to characters that it didn't actually use. The idiom fixed that. As of 1.7.0_06, strings don't share char arrays anymore. – T.J. Crowder Sep 20 '14 at 13:02
  • @HotLicks: Not following you. Strings created via `substring` shared underlying `char` arrays using `offset` and `count` well into **1.7** (specifically, until 1.7.0_06 as I mention above). Just look at the source of `String.java` in 1.7.0_05, specifically lines 1,961 and 645. I must be misunderstanding your comment. – T.J. Crowder Sep 21 '14 at 22:24
  • @HotLicks: Then you're looking at something *after* 1.7.0_05. In 1.7.0_05 (and previously, in the various versions I've looked at), `substring` returns this in the normal case `new String(offset + beginIndex, endIndex - beginIndex, value)` That's a private constructor that just sets `value`, `offset`, and `count`, causing reuse of the `char` array. – T.J. Crowder Sep 21 '14 at 22:40
  • @HotLicks: Exact same code (looks literally untouched) is in 1.1.8_16, 1.2.2_017, and 1.3.1_29. I think you must have been working with non-Sun source, or (due respect!) you're just misremembering (1.2 *was* a long time ago). Since it clearly wasn't junked until 1.7.0_06, we should probably just clean up these comments. – T.J. Crowder Sep 21 '14 at 23:04