1

I read Jon Skeet's answer about concatenating strings with +. I wonder whether the compiler also recognizes appending constand strings with a StringBuffer/StringBuilder.

This code for constructing a URL has a good intention:

StringBuffer sb = new StringBuffer(constant1);
sb.append(nonconstant);
sb.append("?");
sb.append(constant2);
sb.append("=");
sb.append(constant3);
sb.append("&");
sb.append(constant4);
sb.append("=");
sb.append(constant5);

However, if Stringbuffer.append() is not optimized by the compiler for constants, I'd say the following code would be more efficient:

StringBuffer sb = new StringBuffer(constant1);
sb.append(non-constant);
sb.append("?" + constant2 + "=" + constant3 + "&" + constant4 + "=" + constant5);

because the compiler would optimize the + string concatenation at compile time.

1
  • 2
    How about trying it? Compile both snippets and see what the compile does with them. Commented Dec 5, 2014 at 9:58

2 Answers 2

3

Why not try it out? In java 1.7, the main method of the following class:

public class Concat1
{
    private static final String constant2 = "c2";
    private static final String constant3 = "c3";

    public void main(String[] args) 
    {
        StringBuilder sb = new StringBuilder();
        sb.append(args[0]);
        sb.append("?");
        sb.append(constant2);
        sb.append("=");
        sb.append(constant3);
        System.out.println(sb.toString());
    }
}

(I changed the number of constant for clarity) yields the following byte code:

public class Concat1 {
  public Concat1();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: return        

  public void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/StringBuilder
       3: dup           
       4: invokespecial #3                  // Method java/lang/StringBuilder."":()V
       7: astore_2      
       8: aload_2       
       9: aload_1       
      10: iconst_0      
      11: aaload        
      12: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      15: pop           
      16: aload_2       
      17: ldc           #5                  // String ?
      19: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      22: pop           
      23: aload_2       
      24: ldc           #6                  // String c2
      26: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      29: pop           
      30: aload_2       
      31: ldc           #7                  // String =
      33: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      36: pop           
      37: aload_2       
      38: ldc           #8                  // String c3
      40: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      43: pop           
      44: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
      47: aload_2       
      48: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      51: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      54: return        
}

while the following class:

public class Concat2
{
    private static final String constant2 = "c2";
    private static final String constant3 = "c3";

    public void main(String[] args) 
    {
        StringBuilder sb = new StringBuilder();
        sb.append(args[0]);
        sb.append("?" + constant2 + "=" + constant3);
        System.out.println(sb.toString());
    }
}

is compiled to:

public class Concat2 {
  public Concat2();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: return        

  public void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/StringBuilder
       3: dup           
       4: invokespecial #3                  // Method java/lang/StringBuilder."":()V
       7: astore_2      
       8: aload_2       
       9: aload_1       
      10: iconst_0      
      11: aaload        
      12: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      15: pop           
      16: aload_2       
      17: ldc           #5                  // String ?c2=c3
      19: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      22: pop           
      23: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
      26: aload_2       
      27: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      30: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      33: return        
}

So apparently, you are right. In the second class the append method of the StringBuilder is only called twice, while in the first case it is called for each constant string.

Sign up to request clarification or add additional context in comments.

Comments

0

Does the compiler optimize Stringbuffer/StringBuilder.append() for constant strings?

No.

However, I think that the premise of your proposed optimization is incorrect. I suggest that you take the two versions of the code and compile them. Then use javap to see what the compiled code looks like in each case.

(FWIW, I expect that your "optimization" will not improve the generated code. It will most likely create a second StringBuilder to concatenate the intermediate string, and convert that into a String. You end up with roughly the same number of append operations, plus the creation of an extra temporary StringBuilder and an extra temporary String.)

1 Comment

See the referenced answer: "So the compiled version of: String x = "a" + "b"; should be exactly the same as: String x = "ab";"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.