2

I have the following Java code:

String a = "Java" + "Virtual" + "Machine";

For someone 5 objects are created.("Java", "Virtual", "Machine", "Java Virtual", "Java Virtual Machine").

But I know that this code equals that:

String a = new StringBuilder("Java").append("Virtual").append("Machine").toString();

There isn't one object here?

How many String object are created?

edit:

Same question for following code:

String a = "Java";
String b = "Virtual";
String c = a + b + "Machine";

How many String object are created?

Mustafa Çil
  • 766
  • 8
  • 15
  • 2
    String is immutable while StringBuilder isn't. Appending to a String(using +) always returns a new String while appending to a StringBuilder(using the append method) it returns a reference to itself, no new object is created. – anna Feb 15 '16 at 09:07
  • 1
    maybe it got lost, but I added an answer for the second part of your question.. – Neuron Feb 15 '16 at 09:09
  • Your assumption that it is the same as using `StringBuilder` is false. – Mark Rotteveel Feb 15 '16 at 09:15
  • Your sentences starting 'for someone' and 'but I know' are both incorrect. Only one String is created in the case of constant string-literal expressions. Note that this is not an 'optimization', it is a feature of the language. @anna You are mistaken in the case of constant expressions. – user207421 Feb 15 '16 at 09:18
  • @EJP thank you for your comment. Here is another useful example: `String var = "c"; String result = "a" + "b" + var + "d" + "e";` This will be optimized to: `"ab" + var + "d" + "e" `. If `var` was a "static final" variable the compiler would have optimized it like this: `abcde` (compile-time constants). – anna Feb 15 '16 at 11:06
  • @anna I don't know why you're addressing your new example to me. It's the OP who is asking the question. But you're mistaken again. `static` has nothing to do with it. – user207421 Feb 15 '16 at 21:34

2 Answers2

2

There is exact 1 string object created, the compiler optimalizes String a = "Java" + "Virtual" + "Machine"; to String a = "JavaVirtualMachine";.

This can be seem with the output of javap -c Test, I used a System.out.println to prevent the compiler from optimizing it fully away:

Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String...);
    Code:
       0: ldc           #2                  // String JavaVirtualMachine
       2: astore_1
       3: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       6: aload_1
       7: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      10: return
}
Ferrybig
  • 18,194
  • 6
  • 57
  • 79
1

The compiler will optimize the code to equal this:

String a = "JavaVirtualMachine";

The more interesting question is probably what this does:

int x = 5;
String a = "foo" + x + "bar";

In which case the compiler will create a StringBuilder and append all values. This would roughly translate to this code:

int x = 5;
String a = new StringBuilder().append("foo").append(x).append("bar").toString();

But if you are concatenating Strings in a loop, the compiler will create a StringBuilder in each iteration. So if you have a code like this:

String[] errorMessages = getErrorMessages();
String output = "Found the following error messages:";
for(int i = 0; i < errorMessages.length(); i++){
    output += "\n" + (i+1) + ": " + errorMessages[i];
}

This would translate (again roughly) to:

String[] errorMessages = getErrorMessages();
String output = "Found the following error messages:";
for(int i = 0; i < errorMessages.length(); 
    output = new StringBuilder(output).append('\n')
            .append((i+1)).append(": ").append(errorMessages[i]).toString();
}

Like mentioned, this creates a new StringBuilder in each iteration. So in these cases it is better not to rely on the compiler to do it's magic, create your own StringBuilder, and use the same object throughout the whole iteration:

String[] errorMessages = getErrorMessages();
StringBuilder builder = new StringBuilder("Found the following error messages:");
for(int i = 0; i < errorMessages.length(); i++){
    builder.append('\n').append((i+1)).append(": ").append(errorMessages[i]);
}
Neuron
  • 5,141
  • 5
  • 38
  • 59