我读了Jon Skeet's answer about concatenating strings with +。我想知道编译器是否还使用StringBuffer / StringBuilder识别附加constand字符串。
构建URL的代码有一个很好的意图:
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);
但是,如果编译器没有为常量优化Stringbuffer.append(),我会说以下代码会更有效:
StringBuffer sb = new StringBuffer(constant1);
sb.append(non-constant);
sb.append("?" + constant2 + "=" + constant3 + "&" + constant4 + "=" + constant5);
因为编译器会在编译时优化+
字符串连接。
答案 0 :(得分:3)
为什么不尝试一下?在java 1.7中,以下类的主要方法是:
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()); } }
(为了清晰起见,我更改了常量的数量)产生以下字节代码:
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 }
以下课程:
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()); } }
编译为:
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 }显然,你是对的。在第二个类中,
StringBuilder
的append方法只被调用两次,而在第一个例子中,它被调用每个常量字符串。
答案 1 :(得分:0)
编译器是否针对常量字符串优化Stringbuffer / StringBuilder.append()?
没有
但是,我认为您提出的优化的前提是不正确的。我建议您使用两个版本的代码并编译它们。然后使用javap
查看编译代码在每种情况下的样子。
(FWIW,我希望您的"优化"不会改进生成的代码。很可能会创建第二个StringBuilder
来连接中间字符串,并将其转换为String。最终得到大约相同数量的append
操作,再加上创建额外的临时StringBuilder和额外的临时String。)