6
class A { 

String s4 = "abc";

 static public void main(String[]args ) {

        String s1 = "abc";
        String s2 = "abc";
        String s3 = new String("abc");
        A o = new A();
        String s5 = new String("def");

        System.out.println("s1==s2 : " + (s1==s2));
        System.out.println("s1==s1.intern : " + (s1==s1.intern()));
        System.out.println("s1==s3 : " + (s1==s3));
        System.out.println("s1.intern==s3.intern : " + (s1.intern()==s3.intern()));
        System.out.println("s1==s4 : " + (s1==o.s4));
 }
} 

The output:

s1==s2 : true
s1==s1.intern : true
s1==s3 : false
s1.intern==s3.intern : true
s1==s4 : true

My questions:

1.What happens for "String s1 = "abc"? I guess the String object is added to the pool in class String as an interned string? Where is it placed on? The "permanent generation" or just the heap(as the data member of the String Class instance)?

2.What happens for "String s2 = "abc"? I guess no any object is created.But does this mean that the Java Intepreter needs to search all the interned strings? will this cause any performance issue?

3.Seems String s3 = new String("abc") does not use interned string.Why?

4.Will String s5 = new String("def") create any new interned string?

Don Li
  • 1,095
  • 2
  • 12
  • 17

4 Answers4

5
  1. The compiler creates a String object for "abc" in the constant pool, and generates a reference to it in the bytecode for the assignment statement.

  2. See (1). No searching; no performance issue.

  3. This creates a new String object at runtime, because that is what the 'new' operator does: create new objects.

  4. Yes, for "def", but because of (3) a new String is also created at runtime.

The String objects at 3-4 are not interned.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    The compiler creates a String literal in the constant pool. But that is resolved to a reference when the class is loaded. – Jivings May 20 '12 at 10:13
  • @Jivings Wrong how? Comments like that are no use to anybody. – user207421 May 21 '12 at 11:41
  • I already said why in the previous comment. The compiler does not create a String Object. It creates a UTF-8 literal, which is resolved as a reference to the Object in the intern pool during classloading. – Jivings May 21 '12 at 16:43
3

1.What happens for "String s1 = "abc"?

At compile time a representation of the literal is written to the "constant pool" part of the classfile for the class that contains this code.

When the class is loaded, the representation of the string literal in the classfile's constant pool is read, and a new String object is created from it. This string is then interned, and the reference to the interned string is then "embedded" in the code.

At runtime, the reference to the previously created / interned String is assigned to s1. (No string creation or interning happens when this statement is executed.)

I guess the String object is added to the pool in class String as an interned string?

Yes. But not when the code is executed.

Where is it placed on? The "permanent generation" or just the heap(as the data member of the String Class instance)?

It is stored in the permgen region of the heap. (The String class has no static fields. The JVM's string pool is implemented in native code.)

2.What happens for "String s2 = "abc"?

Nothing happens at load time. When the compiler created the classfile, it reused the same constant pool entry for the literal that was used for the first use of the literal. So the String reference uses by this statement is the same one as is used by the previous statement.

I guess no any object is created.

Correct.

But does this mean that the Java Intepreter needs to search all the interned strings? will this cause any performance issue?

No, and No. The Java interpretter (or JIT compiled code) uses the same reference as was created / embedded for the previous statement.

3.Seems String s3 = new String("abc") does not use interned string.Why?

It is more complicated than that. The constructor call uses the interned string, and then creates a new String, and copies the characters of the interned string to the new String's representation. The newly created string is assigned to s3.

Why? Because new is specified as always creating a new object (see JLS), and the String constructor is specified as copying the characters.

4.Will String s5 = new String("def") create any new interned string?

A new interned string is created at load time (for "def"), and then a new String object is created at runtime which is a copy of the interned string. (See previous text for more details.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thanks mate.Your answer looks great. One more question: If the literal is written to the "constant pool" part of the classfile,how come 2 literals(the same contents) in 2 classes use the same interned string? – Don Li May 20 '12 at 12:09
  • @DonLi - the constant pool is a section of a classfile. The classfile spec does not allow one classfile to make reference to the constant pool of another classfile. – Stephen C May 23 '12 at 04:54
2

See this answer on SO. Also see this wikipedia article on String Interning.

Community
  • 1
  • 1
Jeshurun
  • 22,940
  • 6
  • 79
  • 92
-1

String s1 = "abc"; creates a new String and interns it.

String s2 = "abc"; will drag the same Object used for s1 from the intern pool. The JVM does this to increase performance. It is quicker than creating a new String.

Calling new String() is redundant as it will return a new implicit String Object. Not retrieve it from the intern pool.

As Keyser says, == compares the Strings for Object equality, returning true if they are the same Object. When comparing String content you should use .equals()

Jivings
  • 22,834
  • 6
  • 60
  • 101
  • Para 1 creates a new String at compile time. Para 2 ditto: the JVM has nothing to do with it. – user207421 May 20 '12 at 10:06
  • I downvoted before you edited (and closed) your answer, when you said that "abc" and new String("abc") were the same things. – JB Nizet May 20 '12 at 10:10
  • @EJP Incorrect, the compiler places Strings in the constant pool as literals. The JVM decides how to resolve these literals during the resolution stage of ClassLoading. If the String exists in the intern pool then the literal is resolved to that existing Object. – Jivings May 20 '12 at 10:11
  • The JVM Specification #5.4 says that constant pool entries of type ONNSTANT_String are instances of java.lang.String. I would agree that the specs aren't clear about this as they also say that the compiler uses String.intern(), which is manifestly untrue. – user207421 May 20 '12 at 10:18
  • @EJP It is vague. I can assure you that the JVM checks the intern pool during resolution and replaces the CONSTANT_String literal with a String Object reference. The compiler obviously cannot and does not create Java Objects. – Jivings May 20 '12 at 10:23
  • @Jivings You're just guessing about down-votes. The only evidence about that here is from someone else. – user207421 May 21 '12 at 11:49
  • @EJP Apologies, I assumed it was you. – Jivings May 21 '12 at 16:44