259

What is the difference between

String str = new String("abc");

and

String str = "abc";
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
user395617
  • 2,635
  • 3
  • 16
  • 6
  • 3
    Succinct answer: a string object is a **variable**; a string literal is a **constant** (a fixed sequence of characters between quotation marks). [More details](http://mindbugzz.blogspot.co.uk/2012/05/what-is-difference-between-strings-and.html) – Assad Ebrahim Feb 03 '14 at 14:44
  • A String *literal* is a String *object*, but a String *object* is not necessarily a String *literal*. And once assigned to a reference variable, it's all but impossible to tell if a given String object is a *literal* or not. – Hot Licks May 27 '14 at 17:07
  • This was marked as a duplicate of something it doesn't duplicate at all. Not that it's a great question, but others have this one listed as a duplicate correctly, and the duplicate list should end in somethings that's really duplicate. – Don Roby Jan 16 '15 at 18:54
  • I got this question wrong on a Sybex exam because I said it was false: `All String literals are automatically instantiated into a String object.` . The exam seems to think its always true, even if a literal is interned to an already existing object? – djangofan Jan 01 '17 at 21:50

13 Answers13

224

When you use a string literal the string can be interned, but when you use new String("...") you get a new string object.

In this example both string literals refer the same object:

String a = "abc"; 
String b = "abc";
System.out.println(a == b);  // true

Here, 2 different objects are created and they have different references:

String c = new String("abc");
String d = new String("abc");
System.out.println(c == d);  // false

In general, you should use the string literal notation when possible. It is easier to read and it gives the compiler a chance to optimize your code.

nbro
  • 15,395
  • 32
  • 113
  • 196
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 16
    In practice you generally see `new String(...)` used not because someone wants the behavior described here but because they are unaware that strings are immutable. So you see things like `b = new String(a); b = b.substring(2);` rather than just `b = a.substring(2)` as maybe the author is under the impression that the substring method will modify the instance on which it's called. Also while it's true `"abc" == "abc"` I'd say that _in general_ code that relies on this rather than using equals(...) is being clever and prone to confusing things (static final "constants" being an exception). – George Hawkins Jul 23 '10 at 08:53
  • 5
    @broofa: In what way can this be useful in JavaScript? – Randomblue Dec 20 '11 at 00:35
  • What is the importance of this concept ? Saving memory ? – MasterJoe Nov 02 '16 at 23:33
  • You can use `new String("...").intern()` too... – Yousha Aleayoub Oct 13 '17 at 22:41
  • When you use a string literal the string *is* interned, by the rules of the JLS. There is no 'chance' about it. The compiler is obliged to pool these literals. – user207421 Apr 24 '18 at 11:26
90

A String literal is a Java language concept. This is a String literal:

"a String literal"

A String object is an individual instance of the java.lang.String class.

String s1 = "abcde";
String s2 = new String("abcde");
String s3 = "abcde";

All are valid, but have a slight difference. s1 will refer to an interned String object. This means, that the character sequence "abcde" will be stored at a central place, and whenever the same literal "abcde" is used again, the JVM will not create a new String object but use the reference of the cached String.

s2 is guranteed to be a new String object, so in this case we have:

s1 == s2 // is false
s1 == s3 // is true
s1.equals(s2) // is true
nbro
  • 15,395
  • 32
  • 113
  • 196
Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • 18
    Many, many languages have the concept of a String Literal :) – mrk Jun 14 '11 at 05:44
  • 4
    So does this means the literal String "abc" is still an object like `new String("abc")` and the only difference is that it is stored in the intern pool instead of the heap? – yifei Aug 09 '13 at 13:12
  • @yifei yes, that's what it means. – atamanroman Sep 05 '13 at 16:24
  • 1
    So it's mean `string literal is better` because it use same object again and instead of new space? – Asif Mushtaq Mar 14 '16 at 07:16
  • 1
    So in you case, the char arry 'abcde' referenced by s2 is located in heap not string pool? So if you create 100 String object like new String("abc"), in the heap, the abc will have 100 copy? – liam xu May 09 '16 at 05:57
  • I checked, s1 and s2 has same hash and content, but still both are different when compared with `s1==s2`, why so? And as asked by @liamxu, i tried to make 3 copies of s2, i.e. `s4 = new string("abcde");` and `s5 = new string("abcde");` but both have same hashcode. Im less aware of how hash works actually, what `s1.hashcode()` returns? – kAmol Aug 23 '16 at 02:32
  • is there only difference of concept of string pool and heap? As I read It is interesting to note that until Java 7, the pool was in the permgen space of the heap on hotspot JVM but it has been moved to the main part of the heap since Java 7 http://stackoverflow.com/a/14194112/2284107 – kAmol Aug 23 '16 at 02:41
42

The long answer is available here, so I'll give you the short one.

When you do this:

String str = "abc";

You are calling the intern() method on String. This method references an internal pool of String objects. If the String you called intern() on already resides in the pool, then a reference to that String is assigned to str. If not, then the new String is placed in the pool, and a reference to it is then assigned to str.

Given the following code:

String str = "abc";
String str2 = "abc";
boolean identity = str == str2;

When you check for object identity by doing == (you are literally asking: do these two references point to the same object?), you get true.

However, you don't need to intern() Strings. You can force the creation on a new Object on the Heap by doing this:

String str = new String("abc");
String str2 = new String("abc");
boolean identity = str == str2;

In this instance, str and str2 are references to different Objects, neither of which have been interned, so that when you test for Object identity using ==, you will get false.

In terms of good coding practice: do not use == to check for String equality, use .equals() instead.

nbro
  • 15,395
  • 32
  • 113
  • 196
Jon
  • 3,510
  • 6
  • 27
  • 32
  • 1
    You're not really calling intern() by just referencing a literal. You're relying on the compiler having already pooled them and created the String object in the constant area. – user207421 Jul 25 '10 at 04:13
  • 2
    EJB, since when does the compiler create objects? The compiled byte code might run 10 years later on a different machine. It is the job of the JVM to create String objects. And according to the machine language specification (3.10.5), `A string literal is a reference to an instance of class String`. The specification even promises that it will be the same instance across different classes and packages. You might be thinking of a "constant expression". The code `"Hello" + " World"` will be rewritten, by the **compiler**, to `"Hello World"`. – Martin Andersson Aug 17 '13 at 13:28
  • @MartinAnderson Since the [JLS required it to](https://docs.oracle.com/javase/specs/jls/se10/html/jls-3.html#jls-3.10.5), which first happened back in 1995 if not before. The behaviour when encountering a string literal is (1) pooling within the class by the compiler, and (2) pooling within the JVM by the classloader. All these actions take place long before the string literal is 'encountered' by executing the line of code that references it. – user207421 Apr 24 '18 at 11:38
  • I upvoted this answer only because of the explanation. Thanks for making this concept more clear. – Nick Rolando May 07 '18 at 20:42
40

As Strings are immutable, when you do:

String a = "xyz"

while creating the string, the JVM searches in the pool of strings if there already exists a string value "xyz", if so 'a' will simply be a reference of that string and no new String object is created.

But if you say:

String a = new String("xyz")

you force JVM to create a new String reference, even if "xyz" is in its pool.

For more information read this.

Awin
  • 884
  • 7
  • 9
17

"abc" is a literal String.

In Java, these literal strings are pooled internally and the same String instance of "abc" is used where ever you have that string literal declared in your code. So "abc" == "abc" will always be true as they are both the same String instance.

Using the String.intern() method you can add any string you like to the internally pooled strings, these will be kept in memory until java exits.

On the other hand, using new String("abc") will create a new string object in memory, which is logically the same as the "abc" literal. "abc" == new String("abc") will always be false, as although they are logically equal they refer to different instances.

Wrapping a String constructor around a string literal is of no value, it just needlessly uses more memory than it needs to.

nbro
  • 15,395
  • 32
  • 113
  • 196
krock
  • 28,904
  • 13
  • 79
  • 85
  • 1
    "the internally pooled strings will be kept in memory until java exits". I think that at least with modern JVM this is no longer valid, because the GC also collects unused objects in the perm area. Can you confirm that ? – Guido May 08 '11 at 11:45
7

String is a class in Java different from other programming languages. So as for every class the object declaration and initialization is

String st1 = new String();

or

String st2 = new String("Hello"); 
String st3 = new String("Hello");

Here, st1, st2 and st3 are different objects.

That is:

st1 == st2 // false
st1 == st3 // false
st2 == st3 // false

Because st1, st2, st3 are referencing 3 different objects, and == checks for the equality in memory location, hence the result.

But:

st1.equals(st2) // false
st2.equals(st3) // true

Here .equals() method checks for the content, and the content of st1 = "", st2 = "hello" and st3 = "hello". Hence the result.

And in the case of the String declaration

String st = "hello";

Here, intern() method of String class is called, and checks if "hello" is in intern pool, and if not, it is added to intern pool, and if "hello" exist in intern pool, then st will point to the memory of the existing "hello".

So in case of:

String st3 = "hello";
String st4 = "hello"; 

Here:

st3 == st4 // true

Because st3 and st4 pointing to same memory address.

Also:

st3.equals(st4);  // true as usual
nbro
  • 15,395
  • 32
  • 113
  • 196
NCA
  • 810
  • 1
  • 8
  • 19
  • @CaZbaN1 +1 for explaining the intern method intern() for determining whether the value exists on the Heap. – ha9u63a7 Jan 11 '15 at 01:45
6

In the first case, there are two objects created.

In the second case, it's just one.

Although both ways str is referring to "abc".

nbro
  • 15,395
  • 32
  • 113
  • 196
sushil bharwani
  • 29,685
  • 30
  • 94
  • 128
  • Can you explain me how to obj created in first case? – Gautam Savaliya Oct 04 '14 at 09:42
  • @GautamSavaliya In the first case, one object will be created in the String pool to cache the String for further reuse in the code and another object will be created in the heap memory. You can refer this question http://stackoverflow.com/questions/2486191/java-string-pool for more details about String pool. – Sai Upadhyayula Apr 25 '15 at 16:50
5

Some disassembly is always interesting...

$ cat Test.java 
public class Test {
    public static void main(String... args) {
        String abc = "abc";
        String def = new String("def");
    }
}

$ javap -c -v Test
Compiled from "Test.java"
public class Test extends java.lang.Object
  SourceFile: "Test.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method  #7.#16;  //  java/lang/Object."<init>":()V
const #2 = String  #17;     //  abc
const #3 = class   #18;     //  java/lang/String
const #4 = String  #19;     //  def
const #5 = Method  #3.#20;  //  java/lang/String."<init>":(Ljava/lang/String;)V
const #6 = class   #21;     //  Test
const #7 = class   #22;     //  java/lang/Object
const #8 = Asciz   <init>;
...

{
public Test(); ...    

public static void main(java.lang.String[]);
  Code:
   Stack=3, Locals=3, Args_size=1
    0:    ldc #2;           // Load string constant "abc"
    2:    astore_1          // Store top of stack onto local variable 1
    3:    new #3;           // class java/lang/String
    6:    dup               // duplicate top of stack
    7:    ldc #4;           // Load string constant "def"
    9:    invokespecial #5; // Invoke constructor
   12:    astore_2          // Store top of stack onto local variable 2
   13:    return
}
aioobe
  • 413,195
  • 112
  • 811
  • 826
5

In addition to the answers already posted, also see this excellent article on javaranch.

Zaki
  • 6,997
  • 6
  • 37
  • 53
3

According to String class documentation they are equivalent.

Documentation for String(String original) also says that: Unless an explicit copy of original is needed, use of this constructor is unnecessary since Strings are immutable.

Look for other responses, because it seems that Java documentation is misleading :(

nbro
  • 15,395
  • 32
  • 113
  • 196
Michał Niklas
  • 53,067
  • 18
  • 70
  • 114
  • -1 in some sense yes, in other sense no. So your answer is misleading. – Péter Török Jul 21 '10 at 09:35
  • 2
    They're absolutely not equivalent. One will construct a new string each time it's executed and one won't. The strings involved will be *equal*, but that doesn't mean the two expressions will behave exactly the same way. – Jon Skeet Jul 21 '10 at 09:36
  • So documentation lies :( Or maybe I do not understand two first paragraphs of String documentation. – Michał Niklas Jul 21 '10 at 09:38
  • 2
    @Michal: Yes, the documentation is pretty misleading. And that constructor *can* be useful in certain situations as it effectively "trims" the new string to size. – Jon Skeet Jul 21 '10 at 09:40
  • @Michał Niklas: +1 for the confusing Javadoc (as is very common with Java). +1 because it reminds one to take everything written in the Javadocs with a huge grain of salt :) – SyntaxT3rr0r Jul 21 '10 at 09:50
  • I'm having trouble agreeing with some of the above comments. @Jon, @Michal: The doc doesn't say the strings are equal, just that `new()` ing a string is unnecessary. @Jon: Given your reputation I'm hesitant to question your answer, but I don't see any way a cloned String literal would in any way be "trimmed" compared to the original. The only reason I can imagine for using `new("literal")` would be to obtain a String guaranteed not to `==` the otherwise identical (`equal`) original. – Carl Smotricz Jul 21 '10 at 09:51
  • 2
    @Carl, @Michael: To elaborate more on Jon Skeet's comment: using str.substring() returns a new string, referencing the same char array of str. If you don't need str anymore, then use new String(str.substring(..)). Otherwise you may be using much more memory than necessary. – Eyal Schneider Jul 21 '10 at 09:54
  • @Jon: OK, I leave my answer as a proof that documentation isn't perfect :( BTW isn't it implementation detail? And where can I read about such "trims"? – Michał Niklas Jul 21 '10 at 09:54
  • @Carl: Calling that constructor *with a string literal* is mostly pointless, but it's definitely useful when it comes to other cases. In this case I hadn't read the javadoc - it doesn't just say "use of this constructor is unnecessary"... it says "*Unless an explicit copy of original is needed* use of this cosntructor is unnecessary" which is very different. That's fine. However, the *start* of the String javadoc talks about "equivalent" code where it's definitely *not* equivalent. – Jon Skeet Jul 21 '10 at 09:57
  • @Eyal, @Jon: You're correct, but that doesn't apply to the context of this question, because the original String is a literal (and thus assuredly not a substring of an existing string). @Jon: If the doc really mumbles about "equivalent" then it's indeed incorrect; I hadn't looked but just relied on the quote. – Carl Smotricz Jul 21 '10 at 10:05
  • Response edited: I added first part of sentence with "use of this cosntructor is unnecessary". – Michał Niklas Jul 21 '10 at 10:11
2

The following are some comparisons:

String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");

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

System.out.println(s1 == s3);   //false
System.out.println(s1.equals(s3)); //true

s3 = s3.intern();
System.out.println(s1 == s3); //true
System.out.println(s1.equals(s3)); //true

When intern() is called the reference is changed.

nbro
  • 15,395
  • 32
  • 113
  • 196
JavaFreak
  • 21
  • 1
1

There is a subtle differences between String object and string literal.

String s = "abc"; // creates one String object and one reference variable

In this simple case, "abc" will go in the pool and s will refer to it.

String s = new String("abc"); // creates two objects,and one reference variable

In this case, because we used the new keyword, Java will create a new String object in normal (non-pool) memory, and s will refer to it. In addition, the literal "abc" will be placed in the pool.

Parth
  • 141
  • 1
  • 2
  • 14
Kamal
  • 3,878
  • 4
  • 21
  • 24
0

String s = new String("FFFF") creates 2 objects: "FFFF" string and String object, which point to "FFFF" string, so it is like pointer to pointer (reference to reference, I am not keen with terminology).

It is said you should never use new String("FFFF")

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
foret
  • 728
  • 6
  • 14