7

I know there are two ways of creating String in Java:

String a = "aaa";
String b = new String("bbb");

With the first way Java will definitely create a String object in the string pool and make a refer to it. (Assume "aaa" wan't in the pool before.)

With the second method, an object will be created in the heap, but will jvm also create an object in the string pool?

In this post Questions about Java's String pool, @Jesper said:

If you do this:

String s = new String("abc");

then there will be one String object in the pool, the one that represents the literal "abc", > and there will be a separate String object, not in the pool, that contains a copy of the > content of the pooled object.

If that's true, then every time with the new String("bbb");, a object "bbb" is created in the pool, which means by either way above, java will always create a string object in the pool. Then what is intern() used for ? In the docs http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern(), it says:

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

That means there are cases that a string is not in the pool, is that possible ? Which one is true ?

Community
  • 1
  • 1
trojantale
  • 196
  • 1
  • 7
  • 1
    (Edited to make the question less of a duplicate) – mafu Mar 18 '14 at 07:58
  • possible duplicate of [When should we use intern method of String on String constants](http://stackoverflow.com/questions/1855170/when-should-we-use-intern-method-of-string-on-string-constants) – Mark Rotteveel Mar 18 '14 at 08:05

4 Answers4

9

As you know that String is an immutable object in Java programming language, which means once constructed can not be altered. Due to this, JVM has the ability to maintain a literal pool which is helpful to reduce the memory usage and to increase the performance. Each time when a String literal is used JVM checks the literal pool. If the literal is already available, the same reference would be returned. If the literal is not available, a new String object will be created and added in the literal pool.

This theory is applied when you try to create a String like a primitive or a literal/constant.

String str = "bbb";

But when you create a new String object

String str = new String("bbb");

the above mentioned rules are overridden and a new instance is created always.

But the intern API in the String class can be used to pick the String reference from the literal pool even though you create a String using new operator. Please check the below given example. Although the str3 is created using new operator since we used the intern method JVM picked up the reference from the literal pool.

public class StringInternExample {

    public static void main(final String args[]) {

        final String str = "bbb";
        final String str1 = "bbb";
        final String str2 = new String("bbb");
        final String str3 = new String("bbb").intern();

        System.out.println("str == str1 : "+(str == str1));
        System.out.println("str == str2 : "+(str == str2));
        System.out.println("str == str3 : "+(str == str3));
    }
}

Output of above code:

str == str1 : true
str == str2 : false
str == str3 : true

You can have a look: Confusion on string immutability

Source of answer: http://ourownjava.com/java/java-string-immutability-and-intern-method/

Shishir

soLegacy
  • 47
  • 2
  • 11
Shishir Kumar
  • 7,981
  • 3
  • 29
  • 45
6

There are essentially two ways that our String objects can enter in to the pool:

  • Using a literal in source code like "bbb".
  • Using intern.

intern is for when you have a String that's not otherwise from the pool. For example:

String bb = "bbb".substring(1); // substring creates a new object

System.out.println(bb == "bb");          // false
System.out.println(bb.intern() == "bb"); // true

Or slightly different:

System.out.println(new String("bbb").intern() == "bbb"); // true

new String("bbb") does create two objects...

String fromLiteral = "bbb";                     // in pool
String fromNewString = new String(fromLiteral); // not in pool

...but it's more like a special case. It creates two objects because "bbb" refers to an object:

A string literal is a reference to an instance of class String [...].

Moreover, a string literal always refers to the same instance of class String.

And new String(...) creates a copy of it.

However, there are many ways String objects are created without using a literal, such as:

  • All the String methods that perform some kind of mutation. (substring, split, replace, etc.)
  • Reading a String from some kind of input such as a Scanner or Reader.
  • Concatenation when at least one operand is not a compile-time constant.

intern lets you add them to the pool or retrieve an existing object if there was one. Under most circumstances interning Strings is unnecessary but it can be used as an optimization because:

  • It lets you compare with ==.
  • It can save memory because duplicates can be garbage collected.
Community
  • 1
  • 1
Radiodef
  • 37,180
  • 14
  • 90
  • 125
  • So you mean with the `new` keyword, java do create a string object in the pool ? – trojantale Mar 18 '14 at 07:57
  • 3
    @trojantale Using a constructor won't add to the pool. Calling intern does. – Radiodef Mar 18 '14 at 08:01
  • new String("bbb") does create two objects... `String fromLiteral = "bbb"; ` // in pool` `String fromNewString = new String(fromLiteral); // not in pool` You mean `new String("bbb")` is equivalent to those tow lines of code? So using `new String("bbb")` do cause "bbb" interned ? – trojantale Mar 18 '14 at 08:37
  • Yes, `new String("bbb")` is equivalent to those two lines of code. The literal `"bbb"` is itself an object. – Radiodef Mar 18 '14 at 08:40
  • Clear. Also, when I said "with the new keyword, java do create a string object in the pool", I actually mean like `new String("a")`, not others, sorry about the ambiguousness. – trojantale Mar 18 '14 at 08:55
  • OK, then yes, `new String("a")` does create a String in the pool. It's the `"a"` that's in the pool. – Radiodef Mar 18 '14 at 08:58
  • 1
    Right, that's exactly what I mean. – trojantale Mar 18 '14 at 09:00
1

Yes, new String("abc") will create a new object in memory, and thus it is advised to avoid it. Please have a look at item 5 of Josh Bloch's Effective Java, "Avoid creating unnecessary objects" where it is better explained:

As an extreme example of what not to do, consider this statement:

String s = new String("stringette"); // DON'T DO THIS!

The statement creates a new String instance each time it is executed, and none of those object creations is necessary. The argument to the String constructor ("stringette") is itself a String instance, functionally identical to all of the objects created by the constructor. If this usage occurs in a loop or in a frequently invoked method, millions of String instances can be created needlessly. The improved version is simply the following:

String s = "stringette";

This version uses a single String instance, rather than creating a new one each time it is executed. Furthermore, it is guaranteed that the object will be reused by any other code running in the same virtual machine that happens to contain the same string literal [JLS, 3.10.5].

http://uet.vnu.edu.vn/~chauttm/e-books/java/Effective.Java.2nd.Edition.May.2008.3000th.Release.pdf

Jorge_B
  • 9,712
  • 2
  • 17
  • 22
1

With the second method, an object will be created in the heap, but will jvm also create an object in the string pool?

Yes, but it is the string literal "bbb" which ensures the interned string1. The string constructor creates a new string object which is a copy with the same length and content - the newly created string is not automatically interned.

If that's true, then every time with the new String("bbb");, a object "bbb" is created in the pool, which means by either way above, java will always create a string object in the pool. Then what is intern() used for ?

Only string literals are automatically interned. Other string objects must be manually interned, if such is the desired behavior.

That means there are cases that a string is not in the pool, is that possible ?

With the exception of manual calls to String.intern, only string literals result in interned strings.

While I would recommend using a specialized collection for such cases, interning may be useful where it can be used to avoid creating extra duplicate objects. Some use-cases where interning can be beneficial - as in, the same string value can appear many times - is in JSON keys and XML element/attribute names.


1 This is trivial to reason, consider:

String _b = "bbb";          // string from string literal (this is interned)
String b = new String(_b);  // create a NEW string via "copy constructor"
b == _b           // -> false (new did NOT return an interned string)
b.equals(_b)      // -> true  (but it did return an equivalent string)
b.intern() == _b  // -> true  (which interns to .. the same string object)
Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • 1
    @trojantale `new String(x)` simply creates a **new** string; the new string object is *not the same string object as x* (although it has the same length/content) and is *not interned*. – user2864740 Mar 18 '14 at 08:16
  • @trojantale Look at my example which breaks down `new String("bbb")` into two statements. The `_b` variable refers to the *interned string* (from the `"bbb"` string literal), while the string represented by `b` is *not* interned and it is *not* `_b`. – user2864740 Mar 18 '14 at 08:19
  • `new String(x)` create a new string object not the same with x, is x added to the pool ? – trojantale Mar 18 '14 at 08:24
  • @trojantale x is not "added to the pool". Rather, x merely *represents* a string object (i.e. it's a variable name). This string - as in the case of my example - *was* added to the pool **because** it (`"bbb"`) was a *string literal*. Read the comments next to each line. – user2864740 Mar 18 '14 at 08:24
  • I mean with the `new String("bbb")` , is "bbb" added in the pool? Sorry about the misunderstanding. – trojantale Mar 18 '14 at 08:30
  • 1
    @trojantale Yes, but it has *nothing* to do with `new String`. It is added *because and only because* `"bbb"` is a *string literal*. As in my example, `String _b = "bbb";`. There, that is *when/why* it is added to the string pool.. – user2864740 Mar 18 '14 at 08:32
  • @trojantale When you write `"bbb"` in your source code, that is referencing an object. You can give it to a constructor, you can call methods on it. It is referencing an object, not a value. – Radiodef Mar 18 '14 at 08:34
  • 1
    As you said, when using "bbb" in source code, "it is referencing an object", and "It is added because and only because "bbb" is a string literal", I know it has nothing to do with `new String`, but it did cause the "bbb" interned in the pool, right ? So if you use` String b = new String ("bbb")`, either you call `b.intern()` or not, "bbb" is already interned, is that correct ? – trojantale Mar 18 '14 at 08:46