28

As explained in these Stackoverflow questions: question 1 & question 2 I understand that "String literals" are interned when:

String s = "abc"; 

And that the JVM will create a new String object instead of using an existing one from the String Pool when:

String s = new String("abc");

However, I have a doubt after reading the following two similar statements.

When the compiler encounters a String literal, it checks the pool to see if an identical String already exists. If a match is found, the reference to the new literal is directed to the existing String, and no new String literal object is created.

In this case, we actually end up with a slightly different behavior because of the keyword "new." In such a case, references to String literals are still put into the constant table (the String Literal Pool), but, when you come to the keyword "new," the JVM is obliged to create a new String object at run-time, rather than using the one from the constant table.

So if we also put a reference in nonpool memory AND in pool memory when we create an object using "new" and based on the definitions above. Shouldn't the JVM also return the same reference when we do this?:

String one = new String("test");
String two = "test";

System.out.println(one.equals(two)); // true
System.out.println(one == two);      // false

Because when declaring the String literal String three = "test"; it will already exist in the pool? and therefore should return the same reference and print true? or do the previous statements mean that they will be put in pool memory but simply skipped when the new operator is used?

Nicholas K
  • 15,148
  • 7
  • 31
  • 57
Bartzilla
  • 2,768
  • 4
  • 28
  • 37

5 Answers5

33

Maybe this will aid your understanding:

String literal = "test";
String one = new String(literal);
String two = "test";

System.out.println(literal == two); //true
System.out.println(one == two); //false

In the example you posted:

String one = new String("test");
String two = "test";

the reference passed to the constructor String(String) has the same value as the reference two due to interning. However, the string itself (referenced by these two references) is used to construct a new object which is assigned to reference one.

In this example, there are exactly two Strings created with the value "test": the one maintained in the constant pool and referenced whenever you use the literal "test" in an expression, and the second one created by the "new" operator and assigned to the reference one.

Edit

Perhaps you're confused about this statement:

When the compiler encounters a String literal, it checks the pool to see if an identical String already exists.

Note that this might be more clearly stated as:

When the compiler encounters a String literal, it checks to see if an identical String already exists in the pool.

Strings are only put in the pool when they are interned explicitly or by the class's use of a literal. So if you have, for example, this scenario:

String te = "te";
String st = "st";

String test = new String(te) + new String(st);

then while a String will exist with the value test, said String will not exist in the pool as the literal "test" has never occurred.

Mark Peters
  • 80,126
  • 17
  • 159
  • 190
8
    //Creates a new object even if one exists in the pool
    String s1 = new String("Tendulkar");

    // makes a new object string and then the reference is available to the pool
    String s2 = s1.intern();

    //this object is not created but references the address present in the pool
    String s3 = "Tendulkar";

    System.out.print(s1==s2); // results in false
    System.out.print(s2==s3); //very very true !!!
Arun Dutta
  • 119
  • 1
  • 1
2

"abc" puts an object into the constant pool, at compile/class-load time, and new String() creates a new object, at execution time. So new String("abc") does both, but at different phases.

user207421
  • 305,947
  • 44
  • 307
  • 483
2

Your question :

So if we also put a reference in nonpool memory AND in pool memory when we create an object using "new" and based on the definitions above. Shouldn't the JVM also return the same reference when we do this?:

Ans : When you create a new string object by using new keyword, the address generated will be a heap address, not a string constant pooled address. And both the addresses are different.

Questions :

String one = new String("test");
String two = "test";

System.out.println(one.equals(two)); // true
System.out.println(one == two);      // false

do the previous statements mean that they will be put in pool memory but simply skipped when the new operator is used?

Answer : Yes, your assumption is correct. When programmer uses new keyword, JVM will simply ignore about string constant pool, and creates a new copy in the Heap. Hence both the addresses are not same.

user1923551
  • 4,684
  • 35
  • 29
0

Creation of String Literals

  1. Each time you create a string literal, the JVM checks the string constant pool first

  2. If the string already exists in the pool, a reference to the pooled instance is returned

  3. If string doesn't exist in the pool, a new string instance is created and placed in the pool

Example,

    String s1 = "Welcome";
    String s2 = "Welcome"; //will not create new instance

String Literal & String Object

    String str1 = "Hello World!!";
    String str2 = "Hello World!!";
    System.out.println(str1 == str2);// true

When the String literal str2 is created, the string “Hello World” is not created again. Instead, it is str1 String is reused as it is already existing in the string constant pool.

Since both str1 and str2 are referring to the same

    String str3 = new String("Hello World!!");
    String str4 = new String("Hello World!!");
    System.out.println(str3 == str4); // false

In this case, new String objects are created and separately referred by str3 and str4. Thus, str3 == str4 is false. String in the pool, str1 == str2 is true.

shalitha senanayaka
  • 1,905
  • 20
  • 37