views:

519

answers:

11

what is difference between String str = new String("abc"); and String str = "abc";

+18  A: 

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 two 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.

Mark Byers
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
+2  A: 

in first case there are two objects created.

and in case 2 its just one.

Altought both ways str is referring to "abc";

sushil bharwani
A: 

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.

EDITED: Look for other responses becasue it seems that Java documentation is misleading :(

Michał Niklas
-1 in some sense yes, in other sense no. So your answer is misleading.
Péter Török
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
So documentation lies :( Or maybe I do not understand two first paragraphs of String documentation.
Michał Niklas
@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
@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 :)
Webinator
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
@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
@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
@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
@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
Response edited: I added first part of sentence with "use of this cosntructor is unnecessary".
Michał Niklas
+4  A: 

"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.

krock
+6  A: 

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";

are all 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
Andreas_D
+1  A: 

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
A: 

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 don't keen with terminology).
It is said you should never use new String("FFFF")

foret
Not really. FFFF is already there created by the compiler. At runtime either zero or one object is created.
EJP
+3  A: 

The long answer is available elsewhere, 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.

Jon
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.
EJP
A: 

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 itz pool.

For more information read http://javatechniques.com/public/java/docs/basics/string-equality.html

awin
A: 

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

Zaki
A: 

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.

Kamal
Not really, see below.
EJP