Reputation: 59258
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.
Upvotes: 1
Views: 1112
Reputation: 12932
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.
Upvotes: 3
Reputation: 718768
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.)
Upvotes: 0