122

We normally create objects using the new keyword, like:

Object obj = new Object();

Strings are objects, yet we do not use new to create them:

String str = "Hello World";

Why is this? Can I make a String with new?

Michael Myers
  • 188,989
  • 46
  • 291
  • 292
giri
  • 26,773
  • 63
  • 143
  • 176

15 Answers15

145

In addition to what was already said, String literals [ie, Strings like "abcd" but not like new String("abcd")] in Java are interned - this means that every time you refer to "abcd", you get a reference to a single String instance, rather than a new one each time. So you will have:

String a = "abcd";
String b = "abcd";

a == b; //True

but if you had

String a = new String("abcd");
String b = new String("abcd");

then it's possible to have

a == b; // False

(and in case anyone needs reminding, always use .equals() to compare Strings; == tests for physical equality).

Interning String literals is good because they are often used more than once. For example, consider the (contrived) code:

for (int i = 0; i < 10; i++) {
  System.out.println("Next iteration");
}

If we didn't have interning of Strings, "Next iteration" would need to be instantiated 10 times, whereas now it will only be instantiated once.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
danben
  • 80,905
  • 18
  • 123
  • 145
  • 1
    By using String a = new String("abcd"), does it means two string with similar content are present in memory. – changed Jan 05 '10 at 21:54
  • 1
    Right - the compiler will not necessarily check to see if such a String has already been interned (though you could certainly write one that did). – danben Jan 05 '10 at 21:57
  • yes, this optimization is possible because strings are immutable and therefore can be shared without problems. the shared "asdf" handling is an implementation of the 'Flyweight' design pattern. – manuel aldana Jan 06 '10 at 02:51
  • No one said that it isn't possible, only that it isn't guaranteed. Was that your downvote? – danben Jan 06 '10 at 03:37
  • What do you mean by "== tests for object equality"? This doesn't seem true to me, but perhaps you meant something different from what this seems to mean. – Dawood ibn Kareem Nov 30 '14 at 10:10
  • In your example, is a == b; always necessarily true? If a is not used further in the code, there is no guarantee that it hasn't been garbage-collected before String b = "abcd"; is executed. In that case, your compare a==b will be comparing a real String reference (b) to nothing (what used to be a pointer to a). – WhyGeeEx Mar 03 '15 at 13:27
  • "Physical equality" is often referred to as "equal identity". – MC Emperor Mar 12 '17 at 20:48
  • I thought == only returns true, if the two string objects are in the memory location and containing the same chracters? – most venerable sir Oct 18 '17 at 18:57
  • @MCEmperor It is referred to as 'identity'. – user207421 Nov 01 '20 at 09:18
38

Strings are "special" objects in Java. The Java designers wisely decided that Strings are used so often that they needed their own syntax as well as a caching strategy. When you declare a string by saying:

String myString = "something";

myString is a reference to String object with a value of "something". If you later declare:

String myOtherString = "something";

Java is smart enough to work out that myString and myOtherString are the same and will store them in a global String table as the same object. It relies on the fact that you can't modify Strings to do this. This lowers the amount of memory required and can make comparisons faster.

If, instead, you write

String myOtherString = new String("something");

Java will create a brand new object for you, distinct from the myString object.

Jamie McCrindle
  • 9,114
  • 6
  • 43
  • 48
  • Hey ... it doesn't require "infinite wisdom" to recognize the need for some kind of syntactic support for string literals. Just about every other serious programming language design supports some kind of string literal. – Stephen C Jan 05 '10 at 23:54
  • 13
    Hyperbole has been reduced to stun, Captain :) – Jamie McCrindle Jan 06 '10 at 07:45
21
String a = "abc"; // 1 Object: "abc" added to pool

String b = "abc"; // 0 Object: because it is already in the pool

String c = new String("abc"); // 1 Object

String d = new String("def"); // 1 Object + "def" is added to the Pool

String e = d.intern(); // (e==d) is "false" because e refers to the String in pool

String f = e.intern(); // (f==e) is "true" 

//Total Objects: 4 ("abc", c, d, "def").

Hope this clears a few doubts. :)

Crocode
  • 3,056
  • 6
  • 26
  • 31
  • 1
    String d = new String("def"); // 1 Object + "def" is added to the Pool -> here "def" would be added to the pool only if it's not there yet – Kurovsky Jun 25 '15 at 10:51
  • @southerton Meaningless. It already is in the pool. It was placed there by the compiler. – user207421 Feb 07 '16 at 09:35
  • 1
    @EJP why (e==d) is false here? they are both refering to the same object "def" in the pool right ? – Raja Jul 16 '18 at 03:47
  • String c = new String("abc"); // 1 Object ... is this statement correct? If "abc" already referenced from the constant pool then what is the use of inter method? – Prashanth Debbadwar Jun 07 '19 at 16:56
  • @Raja No, `d` refers to a new String, while `e` reters to its interned version. – user207421 Nov 01 '20 at 09:20
  • @user207421 so what is the value of ```d``` and what is the value of ```d.intern()```? What will be the value of ```e``` and ```e.intern()```? And lastly, what will be the value of ```f```? – myverdict Feb 26 '22 at 02:44
10

We usually use String literals to avoid creating unnecessary objects. If we use new operator to create String object , then it will create new object everytime .

Example:

String s1=“Hello“;
String s2=“Hello“;
String s3= new String(“Hello“);
String s4= new String(“Hello“);

For the above code in memory :

enter image description here

Joby Wilson Mathews
  • 10,528
  • 6
  • 54
  • 53
6

It's a shortcut. It wasn't originally like that, but Java changed it.

This FAQ talks about it briefly. The Java Specification guide talks about it also. But I can't find it online.

Malfist
  • 31,179
  • 61
  • 182
  • 269
  • 2
    Broken link, and I am not aware of any other evidence that it was ever changed. – user207421 Feb 07 '16 at 09:34
  • 2
    @EJP It's still in the [wayback machine](http://web.archive.org/web/20130423122845/http://www.codestyle.org/java/faq-Strings.shtml#stringconstructor) if that's useful. – Arjan Aug 15 '16 at 02:54
6

String is subject to a couple of optimisations (for want of a better phrase). Note that String also has operator overloading (for the + operator) - unlike other objects. So it's very much a special case.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
4

In Java, Strings are a special case, with many rules that apply only to Strings. The double quotes causes the compiler to create a String object. Since String objects are immutable, this allows the compiler to intern multiple strings, and build a larger string pool. Two identical String constants will always have the same object reference. If you don't want this to be the case, then you can use new String(""), and that will create a String object at runtime. The intern() method used to be common, to cause dynamically created strings to be checked against the string lookup table. Once a string in interned, the object reference will point to the canonical String instance.

    String a = "foo";
    String b = "foo";
    System.out.println(a == b); // true
    String c = new String(a);
    System.out.println(a == c); // false
    c = c.intern();
    System.out.println(a == c); // true

When the classloader loads a class, all String constants are added to the String pool.

brianegge
  • 29,240
  • 13
  • 74
  • 99
1

Well the StringPool is implemented using The Hashmap in java. If we are creating always with a new keyword its not searching in String Pool and creating a new memory for it which might be needed later if we have a memory intensive operation running and if we are creating all the strings with new keyword that would affect performance of our application. So its advisable to not to use new keywords for creating string because then only it will go to String pool which in turn is a Hashmap ,(memory saved , imagine if we have lots of strings created with new keyword ) here it will be stored and if the string already exists the reference of it(which would usually reside in Stack memory) would be returned to the newly created string. So its done to improve performance .

0

The literal pool contains any Strings that were created without using the keyword new.

There is a difference : String without new reference is stored in String literal pool and String with new says that they are in heap memory.

String with new are elsewhere in memory just like any other object.

Stephan
  • 41,764
  • 65
  • 238
  • 329
lavina
  • 1
  • 1
0

Feel free to create a new String with

String s = new String("I'm a new String");

The usual notation s = "new String"; is more or less a convenient shortcut - which should be used for performance reasons except for those pretty rare cases, where you really need Strings that qualify for the equation

(string1.equals(string2)) && !(string1 == string2)

EDIT

In response to the comment: this was not intended to be an advise but just an only a direct response to the questioners thesis, that we do not use the 'new' keyword for Strings, which simply isn't true. Hope this edit (including the above) clarifies this a bit. BTW - there's a couple of good and much better answers to the above question on SO.

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
0

Syntactic sugar. The

String s = new String("ABC");

syntax is still available.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • 1
    This is not quite right. s=new String("ABC") will not give you the same results as s="ABC". See danben's comment. – Steve B. Jan 05 '10 at 21:41
  • 2
    Also, somewhat ironically, it will first create a String instance representing "ABC" inline - and then pass that as an argument to the constructor call which will create an return a String of identical value. – Andrzej Doyle Jan 06 '10 at 08:39
  • 1
    The valid use case for this constructor is `String small = new String(huge.substring(int, int));`, which allows you to recycle the big underlying `char[]` from the original `huge` String. – Pascal Thivent Jan 26 '10 at 05:39
  • 1
    @PascalThivent yes but not anymore with Java 8. It does not share arrays anymore (in preparation for other optimizations like automatic string deduplication with G1 or upcoming string compression). – eckes Aug 21 '15 at 18:51
  • @AndrzejDoyle Not correct. The compiler creates the object for the literal. – user207421 Feb 07 '16 at 09:35
0

You can still use new String("string"), but it would be harder to create new strings without string literals ... you would have to use character arrays or bytes :-) String literals have one additional property: all same string literals from any class point to same string instance (they are interned).

Peter Štibraný
  • 32,463
  • 16
  • 90
  • 116
0

There's almost no need to new a string as the literal (the characters in quotes) is already a String object created when the host class is loaded. It is perfectly legal to invoke methods on a literal and don, the main distinction is the convenience provided by literals. It would be a major pain and waste of tine if we had to create an array of chars and fill it char by char and them doing a new String(char array).

mP.
  • 18,002
  • 10
  • 71
  • 105
0

Because String is an immutable class in java.

Now why it is immutable? As String is immutable so it can be shared between multiple threads and we dont need to synchronize String operation externally. As String is also used in class loading mechanism. So if String was mutable then java.io.writer could have been changed to abc.xyz.mywriter

Mr37037
  • 738
  • 2
  • 13
  • 29
0
TString obj1 = new TString("Jan Peter");                
TString obj2 = new TString("Jan Peter");                    

if (obj1.Name == obj2.Name)                 
    System.out.println("True");
else                
    System.out.println("False");

Output:

True

I created two separate objects, both have a field(ref) 'Name'. So even in this case "Jan Peter" is shared, if I understand the way java deals..

Tom
  • 16,842
  • 17
  • 45
  • 54