-1

How many objects will be created for the following code?

String temp = "a" + "b" + "c"

My understanding: a,b and c are string literals and will be stored on the string pool (so no new object created). Then while appending using "+" operator it uses StringBuffer internally so 1 object will be created which will hold "abc"(StringBuffer). And it will be returned in a new String object (Whose value will be "abc").

-> So as per me total 2 objects will be created during this operation.(one String and one StringBuffer).

-> Also String "abc" will NOT be present in String Pool.

Am I wrong?

Cœur
  • 37,241
  • 25
  • 195
  • 267
learner
  • 1,095
  • 2
  • 18
  • 41
  • 5
    Actually the compiler will just compile this to "abc". Only one object will be created and added to the string pool at runtime. – Natan Cox Jun 01 '14 at 15:16
  • @Natan, Can you please explain? I am still confused. – learner Jun 01 '14 at 15:24
  • At compilation time the compiler sees you are adding 3 constants "a", "b" and "c" and will happily concatenate them and store "abc" in your variable temp. The situation would be completely different if you would use variables like a, b and c. – Natan Cox Jun 01 '14 at 15:28
  • No StringBuffer is every created because the compiler is allowed to optimze `"a" + "b" + "c"` to `"abc"` while it compiles. Rephrase the OP question to read `String a = "a"; String b = "b"; String c = "c"; String temp = a + b + c;` and you would be more correct, but then you would be forgetting the internal `char[]` inside the `StringBuffer` – Erwin Bolwidt Jun 01 '14 at 15:31

1 Answers1

4

From this test code:

public class Test {
    public static void main(final String[] args) {
        String temp = "a" + "b" + "c";
    }
}

You get this bytecode:

public static void main(java.lang.String[]);
  Code:
     0: ldc           #2                  // String abc
     2: astore_1      
     3: return 

With this constant pool:

Constant pool:
   #1 = Methodref          #4.#13         //  java/lang/Object."<init>":()V
   #2 = String             #14            //  abc
   #3 = Class              #15            //  Test
   #4 = Class              #16            //  java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Utf8               LineNumberTable
   #9 = Utf8               main
  #10 = Utf8               ([Ljava/lang/String;)V
  #11 = Utf8               SourceFile
  #12 = Utf8               Test.java
  #13 = NameAndType        #5:#6          //  "<init>":()V
  #14 = Utf8               abc
  #15 = Utf8               Test
  #16 = Utf8               java/lang/Object

So you were incorrect. One String was created -- "abc" -- and placed into the String pool at runtime.

The compiler here performed constant folding and simplified the compile-time constant expression "a" + "b" + "c" to "abc". You can see this if you compile with the -XD-printflat flag, which shows the actual source that the compiler compiles to bytecode:

public static void main(final String[] args) {
    String temp = "abc";
}

If you want to see actual String concatenation, you'll have to work with operands that aren't compile-time constants, such as variables:

public static void main(final String[] args) {
    String a = "a";
    String b = "b";
    String c = "c";
    String temp = a + b + c;
}

Gets compiled to:

public static void main(java.lang.String[]);
  Code:
     0: ldc           #2                  // String a
     2: astore_1      
     3: ldc           #3                  // String b
     5: astore_2      
     6: ldc           #4                  // String c
     8: astore_3      
     9: new           #5                  // class java/lang/StringBuilder
    12: dup           
    13: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
    16: aload_1       
    17: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    20: aload_2       
    21: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    24: aload_3       
    25: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    28: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
    31: astore        4
  33: return        
awksp
  • 11,764
  • 4
  • 37
  • 44
  • The Stringbuffer object which will be created(As the concept says) will be ready for Gc. Do you mean NO StringBuffer object is ever created during this operation? IF so how does "+" worked here? – learner Jun 01 '14 at 15:27
  • @learner Just updated. Essentially, the compiler sees that you have some compile-time constants, so it can optimize that away by doing the operation at compile-time instead of at runtime. Kind of like if you do `int x = 1 + 2;`, it'll be more efficient to evaluate that at compile time and simply compile `int x = 3;` instead of wasting execution resources performing a simple addition of constants. – awksp Jun 01 '14 at 15:30
  • if the compiler does compile time computation then should it not put "abc" only in String pool and not on heap as an object? So no new object will be created but one string literal(abc) on pool only. Little confused :( – learner Jun 01 '14 at 15:34
  • 1
    @learner Yep, `"abc"` was placed into the `String` pool. If memory serves, the `String` pool actually contains `String` objects, so an object will indeed be created. This makes sense because references have to point to an underlying object, so there has to be `String` object at some point. Also, the `String` pool is indeed located on the heap, as it contains objects. – awksp Jun 01 '14 at 15:40
  • So, if I use operands then I will have two objects(what I mentioned in original question) but if I talk of literals at compile time then it will be 1 because of the reason that you explained. Right? – learner Jun 01 '14 at 15:51
  • @learner Close. If you use non-compile-time constants (i.e. variables), you'll end up with at least one `StringBuilder` and a varying number of other objects based on the types of the other variables you are concatenating. If you use compile-time constants, like in your question, you'll have a single object. Your original question uses compile-time constants, so you'll end up with a single object. – awksp Jun 01 '14 at 15:53