What is the difference between "text" and new String("text")?
Asked Answered
L

13

245

What is the difference between these two following statements?

String s = "text";

String s = new String("text");
Levorotation answered 16/6, 2010 at 10:29 Comment(4)
Related topic: JEP 192: String Deduplication in G1.Liatris
Anyone please reply to this. String a = "Java"; String b = "Java"; System.out.println(a == b); true // but System.out.println("a==b?"+a == b); //false...Gorman
i don't understand when i added some comment ("a==b ?) => my result becomes FALSE. why?Gorman
@Gorman The result is false because order of operations dictates that the + operator goes first, concatenating "a==b ?" with a to create a String "a==b?Java". Then the expression "a==b?Java" == b evaluates to false.Midriff
G
230

new String("text"); explicitly creates a new and referentially distinct instance of a String object; String s = "text"; may reuse an instance from the string constant pool if one is available.

You very rarely would ever want to use the new String(anotherString) constructor. From the API:

String(String original) : Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string. Unless an explicit copy of original is needed, use of this constructor is unnecessary since strings are immutable.

Related questions


What referential distinction means

Examine the following snippet:

    String s1 = "foobar";
    String s2 = "foobar";

    System.out.println(s1 == s2);      // true

    s2 = new String("foobar");
    System.out.println(s1 == s2);      // false
    System.out.println(s1.equals(s2)); // true

== on two reference types is a reference identity comparison. Two objects that are equals are not necessarily ==. It is usually wrong to use == on reference types; most of the time equals need to be used instead.

Nonetheless, if for whatever reason you need to create two equals but not == string, you can use the new String(anotherString) constructor. It needs to be said again, however, that this is very peculiar, and is rarely the intention.

References

Related issues

Guillotine answered 16/6, 2010 at 10:30 Comment(6)
If i write: String s = new String("abc"); And now i write: String s = "abc"; Will String s = "abc"; create a new String literal in the String pool?Constrained
Why nobody answer preceding question?Hynes
@KaveeshKanwal No, the literal won't be duplicated. As you can see there are 2 "abc"s. Only one of them will go to the String pool, and the other one will refer to it. Then there's the s which will be proper new object.Demineralize
@Kaveesh Kanwal - String s = new String("abc") will only create a new String object with value "abc". And the 2nd statement will check if there is any "abc" string literal is already present in String Pool or not. If already present then reference to the existing one is returned and if not then new literal ("abc") is created in String pool. Hope it resolves your query !!Mcmillin
There is no 'may' about it. The compiler must pool string literals. JLS 3.10.5.Clingstone
new String() is useful when you want to take a substring but not keep around a reference to the original (which people say the substring() method does).Hulsey
A
148

String literals will go into String Constant Pool.

The below snapshot might help you to understand it visually to remember it for longer time.

enter image description here


Object creation line by line:

String str1 = new String("java5");

Using string literal "java5" in the constructor, a new string value is stored in string constant pool. Using new operator, a new string object is created in the heap with "java5" as value.

String str2 = "java5"

Reference "str2" is pointed to already stored value in string constant pool

String str3 = new String(str2);

A new string object is created in the heap with the same value as reference by "str2"

String str4 = "java5";

Reference "str4" is pointed to already stored value in string constant pool

Total objects : Heap - 2, Pool - 1

Further reading on Oracle community

Ashia answered 8/5, 2014 at 15:26 Comment(8)
Good answer.. but weant to know that now i am giong to change value of str1="java6" then it will change value of str4?Fellatio
yes i had check it will not change the value of str4Fellatio
@Ashia Can you provide documentation of your Answer’s assertion?Liatris
@Braj: Are the headers for the 'Heap' & 'pool' in the table supposed to be reverse ?Bon
Not correct. The constant pool is created at compile time, not at execution time. Don't use quote formatting for text that isn't quoted.Clingstone
@EJP Can you please elaborate with finer details? Constant pool is residing in memory right and hence I am able to visualise it being created and modified at runtime only. In the above example, what will go wrong considering the fact that pool is created at compile time?Unloose
At compile time,string literals in the class are accumulated (the action of pooling) (only one occurrence of that literal will be available even if it appears many times) in one place in bytecode (in stringpool section) so that on "class load" these pooled strings are actually created in memory (might be inside a section of the heap) ... While the actual execution of the bytecode instructions it will refer (load from this pool) to this pool in memory. javap -verbose will give you an idea.Unloose
Exactly, so 'using string literal "java5" in the constructor, a new string value is stored in string constant pool' remains incorrect. It has already happened prior to execution of this code.Clingstone
O
16

One creates a String in the String Constant Pool

String s = "text";

the other one creates a string in the constant pool ("text") and another string in normal heap space (s). Both strings will have the same value, that of "text".

String s = new String("text");

s is then lost (eligible for GC) if later unused.

String literals on the other hand are reused. If you use "text" in multiple places of your class it will in fact be one and only one String (i.e. multiple references to the same string in the pool).

Orosco answered 16/6, 2010 at 10:32 Comment(2)
Strings in the constant pool are never lost. Did you mean to say 's' is lost if later unused?Clingstone
@EJP: yes, I did mean "s". Thanks for noticing. I will correct the question.Orosco
M
10

JLS

The concept is called "interning" by the JLS.

Relevant passage from JLS 7 3.10.5:

Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.

Example 3.10.5-1. String Literals

The program consisting of the compilation unit (§7.3):

package testPackage;
class Test {
    public static void main(String[] args) {
        String hello = "Hello", lo = "lo";
        System.out.print((hello == "Hello") + " ");
        System.out.print((Other.hello == hello) + " ");
        System.out.print((other.Other.hello == hello) + " ");
        System.out.print((hello == ("Hel"+"lo")) + " ");
        System.out.print((hello == ("Hel"+lo)) + " ");
        System.out.println(hello == ("Hel"+lo).intern());
    }
}
class Other { static String hello = "Hello"; }

and the compilation unit:

package other;
public class Other { public static String hello = "Hello"; }

produces the output:

true true true true false true

JVMS

JVMS 7 5.1 says:

A string literal is a reference to an instance of class String, and is derived from a CONSTANT_String_info structure (§4.4.3) in the binary representation of a class or interface. The CONSTANT_String_info structure gives the sequence of Unicode code points constituting the string literal.

The Java programming language requires that identical string literals (that is, literals that contain the same sequence of code points) must refer to the same instance of class String (JLS §3.10.5). In addition, if the method String.intern is called on any string, the result is a reference to the same class instance that would be returned if that string appeared as a literal. Thus, the following expression must have the value true:

("a" + "b" + "c").intern() == "abc"

To derive a string literal, the Java Virtual Machine examines the sequence of code points given by the CONSTANT_String_info structure.

  • If the method String.intern has previously been called on an instance of class String containing a sequence of Unicode code points identical to that given by the CONSTANT_String_info structure, then the result of string literal derivation is a reference to that same instance of class String.

  • Otherwise, a new instance of class String is created containing the sequence of Unicode code points given by the CONSTANT_String_info structure; a reference to that class instance is the result of string literal derivation. Finally, the intern method of the new String instance is invoked.

Bytecode

It is also instructive to look at the bytecode implementation on OpenJDK 7.

If we decompile:

public class StringPool {
    public static void main(String[] args) {
        String a = "abc";
        String b = "abc";
        String c = new String("abc");
        System.out.println(a);
        System.out.println(b);
        System.out.println(a == c);
    }
}

we have on the constant pool:

#2 = String             #32   // abc
[...]
#32 = Utf8               abc

and main:

 0: ldc           #2          // String abc
 2: astore_1
 3: ldc           #2          // String abc
 5: astore_2
 6: new           #3          // class java/lang/String
 9: dup
10: ldc           #2          // String abc
12: invokespecial #4          // Method java/lang/String."<init>":(Ljava/lang/String;)V
15: astore_3
16: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #6          // Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_2
27: invokevirtual #6          // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_1
34: aload_3
35: if_acmpne     42
38: iconst_1
39: goto          43
42: iconst_0
43: invokevirtual #7          // Method java/io/PrintStream.println:(Z)V

Note how:

  • 0 and 3: the same ldc #2 constant is loaded (the literals)
  • 12: a new string instance is created (with #2 as argument)
  • 35: a and c are compared as regular objects with if_acmpne

The representation of constant strings is quite magic on the bytecode:

and the JVMS quote above seems to say that whenever the Utf8 pointed to is the same, then identical instances are loaded by ldc.

I have done similar tests for fields, and:

  • static final String s = "abc" points to the constant table through the ConstantValue Attribute
  • non-final fields don't have that attribute, but can still be initialized with ldc

Conclusion: there is direct bytecode support for the string pool, and the memory representation is efficient.

Bonus: compare that to the Integer pool, which does not have direct bytecode support (i.e. no CONSTANT_String_info analogue).

Malemute answered 15/4, 2017 at 7:18 Comment(0)
S
3

Any String literal gets created inside string literal pool and the pool doesn't allow any duplicates. Thus if two or more string objects are initialized with the same literal value then all objects will point to the same literal.

String obj1 = "abc";
String obj2 = "abc";

"obj1" and "obj2" will point to the same string literal and the string literal pool will have only one "abc" literal.

When we create a String class object using the new keyword the string thus created is stored in heap memory. Any string literal passed as parameter to the constructor of String class however is stored in string pool. If we create multiple objects using the same value with the new operator a new object will be created in the heap each time, because of this new operator should be avoided.

String obj1 = new String("abc");
String obj2 = new String("abc");

"obj1" and "obj2" will point to two different objects in the heap and the string literal pool will have only one "abc" literal.

Also something that is worth noting with regards to the behavior of strings is that any new assignment or concatenation done on string creates a new object in memory.

String str1 = "abc";
String str2 = "abc" + "def";
str1 = "xyz";
str2 = str1 + "ghi";

Now in the above case:
Line 1: "abc" literal is stored in string pool.
Line 2: "abcdef" literal gets stored in the string pool.
Line 3: A new "xyz" literal is stored in the string pool and "str1" starts to point to this literal.
Line 4: Since the value is generated by appending to another variable the result is stored in the heap memory and the literal being appended "ghi" will be checked for its existence in the string pool and will be created since it doesn't exist in the above case.

Starlight answered 15/1, 2019 at 14:7 Comment(0)
S
2

@Braj : i think u have mentioned the other way around. Please correct me if i am wrong

Object creation line by line:

String str1 = new String("java5")

   Pool- "java5" (1 Object)

   Heap - str1 => "java5" (1 Object)

String str2 = "java5"

  pool- str2 => "java5" (1 Object)

  heap - str1 => "java5" (1 Object)

String str3 = new String(str2)

  pool- str2 => "java5" (1 Object)

  heap- str1 => "java5", str3 => "java5" (2 Objects)

String str4 = "java5"

  pool - str2 => str4 => "java5" (1 Object)

  heap - str1 => "java5", str3 => "java5" (2 Objects)
Shoal answered 7/7, 2015 at 2:32 Comment(1)
str1 is not involved in the value of str2 or str3 or str4 in any way.Clingstone
B
1

Think of "bla" being a magic factory like Strings.createString("bla") (pseudo). The factory holds a pool of all strings yet created this way.

If it gets invoked, it checks if there is already string in the pool with this value. If true, it returns this string object, hence to strings obtained this way are indeed the same object.

If not, it creates a new string object internally, saves it in the pool and then returns it. Thus, when the same string value is queried the next time, it returns the same instance.

Manually creating new String("") overrides this behaviour by bypassing the string literal pool. So equality should always be checked using equals() which compares the character sequence instead of the object reference equality.

Balduin answered 16/6, 2010 at 10:46 Comment(1)
The 'magic factory' you refer to is nothing more or less than the Java compiler. It is a mistake to write of this process as though it occurred at runtime.Clingstone
C
1

One simple way to understand the difference is below:-

String s ="abc";
String s1= "abc";
String s2=new String("abc");

        if(s==s1){
            System.out.println("s==s1 is true");
        }else{
            System.out.println("s==s1 is false");
        }
        if(s==s2){
            System.out.println("s==s2 is true");
        }else{
            System.out.println("s==s2 is false");
        }

output is

s==s1 is true
s==s2 is false

Thus new String() will always create a new instance.

Cindicindie answered 16/6, 2010 at 11:19 Comment(0)
H
1

Although it looks the same from a programmers point of view, it has big performance impact. You would want to use the first form almost always.

Hulburt answered 17/6, 2010 at 4:38 Comment(0)
M
1

Sorry for late Answer but much needed Answer. First we need to know some Java.lang.String Class rules.

  1. String Literals e.g.String str="java"; (we use only double Quotes) are different from String Object (we use new keyword) e.g. String str=new String("java");

  2. String is Immutable Object i.e. If value changes a new Object is created and returned to you eg See replace() and replaceAll() functions and many more.

  3. This creates a problem of many String Object in Modification, So creators of Java came up an Idea was called StringPool. StringPool is stored in heap area where object reference data will be stored as we know String is Char[](before java 9 very Long to read) or byte[](after java 9 short to read).

  4. String literals are stored in StringPool and String Objects are stored in as usual heap Object Area.

  5. If there are many Object String Initialization JVM heap will be finished in String Operations only, Java Development team came up with intern() solution this moves/changes memory reference to StringPool.

    Program: Comparing String references to objects

Another good link to understand java.lang.String better

import java.util.*; 

class GFG { 
    public static void main(String[] args) 
    { 
      String siteName1 = "java.com";
        String siteName2 = "java.com";
        String siteName3 = new String("java.com");
        String siteName4 = new String("java.com").intern();
      
    System.out.println("siteName1:::"+Integer.toHexString(System.identityHashCode(siteName1)));
      System.out.println("siteName2:::"+Integer.toHexString(System.identityHashCode(siteName2)));
      System.out.println("siteName3 creation Of New Object Without Interned:::"+Integer.toHexString(System.identityHashCode(siteName3)));//must be Diffrent bcoz new Object In Heap Area
      System.out.println("siteName4 creation Of New Object With Interned:::"+Integer.toHexString(System.identityHashCode(siteName4)));//must be same MemoryAddress of siteName1,siteName2 and Interned, bcoz Objects Points to String pool Now
      
      System.out.println(siteName1 == siteName2); // true
      System.out.println(siteName1 == siteName3); // false this tells about lietral vs String Objects
      String siteName5 = siteName3.intern(); // Interning will not change Original Object but gives us a new Object
      
      System.out.println("siteName5 Interned from siteName3:::"+Integer.toHexString(System.identityHashCode(siteName5)));//must be same MemoryAddress of siteName1,siteName2 and Interned, bcoz Objects Points to String pool Now
      
      System.out.println(siteName1 == siteName3); // false this tells about Immutability
      System.out.println(siteName1 == siteName5); // true After Intering both are same
      System.out.println(siteName1 == siteName4); // true
      System.out.println(siteName5 == siteName4); // true
    } 
}
Mikes answered 9/8, 2020 at 9:33 Comment(0)
A
1

When you use some thing like new String("Hello World") the SpotBugs code analyze tool, complains a performance issue.

The description of this issue shows deference of new and constant string

Using the java.lang.String(String) constructor wastes memory because the object so constructed will be functionally indistinguishable from the String passed as a parameter.  Just use the argument String directly.
Bug kind and pattern: Dm - DM_STRING_CTOR

Assagai answered 1/11, 2022 at 7:22 Comment(0)
P
0
String str = new String("hello")

It will check whether String constant pool already contains String "hello"? If present then it will not add an entry in String constant pool. If not present then it will add an entry in String constant pool.

An object will be created in a heap memory area and str reference points to object created in heap memory location.

if you want str reference to point object containing in String constant pool then one has to explicitly call str.intern();

String str = "world";

It will check whether String constant pool already contains String "hello"? If present then it will not add an entry in String constant pool. If not present then it will add an entry in String constant pool.

In both the above case, str reference points to String "world" present in Constant pool.

Plectognath answered 15/9, 2015 at 10:24 Comment(5)
'It' being the Java compiler. The string literal creates a unique entry in the constant pool, at compile time. It's a mistake to deacribe this process as though it happens at runtime..Clingstone
Can you please explain what is wrong in this post clearly?Plectognath
What is wrong in this post is that the string literal is pooled at complle time, as I already said. Not when executing the code, as in your answer.Clingstone
@EJP I appreciate your response. Can you please point out the exact line which is wrong in answer. I see all answers above are same as what i wrote. Please help, I want to correct my understanding. Thanks.Plectognath
You have written about the entire process as though it all takes place when the line of code is executed, which, as I have repeatedly told you, is not the case. You can't reduce all that to a single 'exact line' being wrong in your answer.Clingstone
N
0

When you store a String as

String string1 = "Hello";

directly, then JVM creates a String object with the given price during a separate block of memory called String constant pool.

And whenever we have a tendency to try and produce another String as

String string2 = "Hello";

JVM verifies whether or not any String object with constant price exists within the String constant pool, if so, rather than making a brand new object JVM assigns the reference of the existing object to the new variable.

And when we store String as

String string = new String("Hello");

using the new keyword, a brand new object with the given price is made no matter the contents of the String constant pool.

Newsletter answered 27/1, 2019 at 10:41 Comment(1)
"String constant pool" can be confusing: 1) there is the (run-time) constant pool, also for string constants (JVMS;) and 2) there is the pool of strings (of the String class) javadoc - both unrelatedBraze

© 2022 - 2024 — McMap. All rights reserved.