6

Possible Duplicate:
Questions about Java’s String pool

I have a doubt in java Strings object creation.

String s1 = "Hello"+"world";
String s2 = s1+"Java";

in this program how many String objects will be created and how ?please explain it. Thanks.

Community
  • 1
  • 1
AndroidCrazy
  • 334
  • 8
  • 23

7 Answers7

5

The answer is 3

Two String objects will be created once per JVM start:

  • "Helloworld"
  • "Java"

Both will be interned, because they are constants (known at compile time).

They will be reused every time this code runs. A StringBuilder will be created to concatenate the two String above. References to them will be assigned to s1 and s2.

Here's the bytecode for the code:

   0:   ldc #37; //String Helloworld
   2:   astore_1
   3:   new #39; //class java/lang/StringBuilder
   6:   dup
   7:   aload_1
   8:   invokestatic    #41; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   11:  invokespecial   #47; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
   14:  ldc #50; //String Java
   16:  invokevirtual   #52; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   19:  invokevirtual   #56; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   22:  astore_2
   23:  return
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • 3
    Hmmm. I was going to say four, because the concatenation operator doesn't append but instead instantiates a new string. Do you by chance have a reference link? what about the s1, which isn't a constant? – jamesmortensen Jan 07 '13 at 04:23
  • 1
    @jmort253 although s1 is a "variable", the value of s1 is determinable at compile time, so a internal String constant is created for it (see link). This answer is correct. Note that the question asks how many String Objects are created, not String references. – Bohemian Jan 07 '13 at 04:31
  • Hi @Nambari, check out the interned link, which specifically mentions Java in this context. Bohemian, thanks for the link. +1 – jamesmortensen Jan 07 '13 at 04:32
  • Also check out jls 15.28. – yshavit Jan 07 '13 at 05:27
  • 1
    @jmort253 Actually I was *half* right (but right now) see edited answer with "proof" – Bohemian Jan 07 '13 at 05:37
  • I'm not up to speed on my bytecode, so I'm honestly not 100% sure what's going on here, but from the code comments it does look like StringBuilder is used for the concatenation operations, which does reduce the number of Strings instantiated. – jamesmortensen Jan 07 '13 at 05:48
  • Sorry to be pedantic, but the proof is in the JLS, not in the bytecode. :) The StringBuilder stuff is implementation-specific, for instance. – yshavit Jan 07 '13 at 14:54
  • @Bohemian is [this just useful or brilliant?](http://meta.stackexchange.com/questions/148066/can-i-search-my-comments-using-some-keywords/161869#161869) on the mission of a feature request :) – bonCodigo Jan 07 '13 at 20:43
5

You can't really say, how many Strings are created, since there's several differences due to the different implementations of the JVM.

As String is an immutable class, the naive answer is 5. But with some optimization (e.g. using a StringBuffer/ StringBuilder there would only be 2 Strings.

As concats would be summarized via append()-calls.

Edit: As the're some different answers here an explanation why I said 5:

  1. "Hello"
  2. "world"
  3. (s1) "Helloworld"
  4. "Java"
  5. (s2) "HelloworldJava"
jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
Zhedar
  • 3,480
  • 1
  • 21
  • 44
  • 1
    No, the JLS specifically defines compile-time constant string expressions. There will be two string constants and one string created at runtime. Jls 15.28. – yshavit Jan 07 '13 at 05:28
  • Well that's the part I said about the classes `Stringbuffer`and `StringBuilder`. Those will be used by the compiler to minimize the number of used literals. – Zhedar Jan 07 '13 at 05:44
  • I understand, but strings 1 and 2 in your list will _not_ be created by a JVM that's up to spec, because string 3 in your list is a *compile-time* constant per the spec. Similarly, string 5 is _not_ a compile-time constant and therefore must create a new String (jls 15.18.1). – yshavit Jan 07 '13 at 14:33
  • And just to close the circle, the one thing that is implementation-specific is how many interim Strings are created by the concatenation. In the case of two strings, it's no different using direct concats vs StringBuilder. The compiler could I guess go crazy and create the string one char at a time, so that there's as many interim strings as chars, but that'd be pretty silly. – yshavit Jan 07 '13 at 14:48
2

if you look at the compiled code, you can easily guess:

String s1 = "Helloworld";
String s2 = (new StringBuilder(String.valueOf(s1))).append("Java").toString();

We can't accurately know by just looking at source code as many optimizations are done by the compiler before execution.

Here we see that 1 String object is created for s1, and another String object for s2. Here 2 string literals are there in the string pool: "Helloworld" and "Java"

vishal_aim
  • 7,636
  • 1
  • 20
  • 23
1

If you decompile your Program.class you will see the real code

String s1 = "Helloworld";
String s2 = (new StringBuilder(String.valueOf(s1))).append("Java").toString();

10 objects it seems, because inside each String there is char[] value this is a separate object + another char[] inside StringBuilder

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
0

The answer is 3.

You can view the deassembled result by:

javap -verbose YourClass

The Constant pool includes:

...
const #17 = Asciz       Helloworld;
...
const #30 = Asciz       Java;
...

It means two strings ("Helloworld" and "Java") are compile-time constant expression which will be interned into constant pool automatically.

The code:

Code:
 Stack=3, Locals=3, Args_size=1
 0:   ldc     #16; //String Helloworld
 2:   astore_1
 3:   new     #18; //class java/lang/StringBuilder
 6:   dup
 7:   aload_1
 8:   invokestatic    #20; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
 11:  invokespecial   #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
 14:  ldc     #29; //String Java
 16:  invokevirtual   #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 19:  invokevirtual   #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
 22:  astore_2
 23:  return

It indicates that s2 is created by StringBuilder.append() and toString().

To make this more interesting, javac can optimize the code in constant folding. You can guess the count of strings created by the following code:

final String s1 = "Hello" + "world";
String s2 = s1 + "Java";

"final" means s1 is constant which can help javac to build the value of s2 and intern s2. So the count of string created here is 2.

Jacky
  • 8,619
  • 7
  • 36
  • 40
-1

Yup, there will be be five String objects created. Strings are immutable; followings are the steps - 1. First "Hello" 2. then another objects "Hello World" 3. then another object "Java" 4. then s1+"Java" and then finally s2 would be created.

Kumar Shorav
  • 531
  • 4
  • 16
-2

Actually no String objects will be created just two String literals. When Strings are initialized like you have they are literals not objects. If you wanted to create String objects you would do the following

String a = new String("abcd");
Will Jamieson
  • 918
  • 1
  • 16
  • 32