Java编译器将StringBuilder替换为+;串联
下面是一些简单的Java代码:Java编译器将StringBuilder替换为+;串联,java,stringbuilder,compiler-optimization,Java,Stringbuilder,Compiler Optimization,下面是一些简单的Java代码: String s = new StringBuilder().append("a").append("b").append("c").toString(); 我使用JRE 1.6编译它,在反编译的类文件中观察到以下内容: String s = "a" + "b" + "c"; 我有以下问题: 为什么编译器选择“+”而不是StringBuilder 我们是否有任何正式的Java规范来证明这种行为 在这种情况下使用StringBuilder真的有意义吗?我们知道编
String s = new StringBuilder().append("a").append("b").append("c").toString();
我使用JRE 1.6编译它,在反编译的类文件中观察到以下内容:
String s = "a" + "b" + "c";
我有以下问题:
相反<
String
的代码>+在后台使用StringBuilder
(或StringBuffer
)实现(请参阅或)
因此,一旦编译完成,您的两个代码片段就无法区分。反编译器必须猜测原始形式
append
的字节码指令来自使用+
运算符的源代码StringBuffer
或类似方法在String
s之间实现+
运算符:
实现可以选择在一个步骤中执行转换和连接,以避免创建然后丢弃中间字符串对象。为了提高重复字符串连接的性能,Java编译器可以使用StringBuffer类或类似技术来减少通过表达式求值创建的中间字符串对象的数量
StringBuilder
类是一种“类似的技术”StringBuilder
并自己附加它们我不确定JDK1.6(javac是JDK的一部分),但当我用JDK1.7编译它时,我得到了一个合适的答案 编译器很聪明。在JDK中,我认为如果有s=“a”+“b”+“c”,它可能会这样做(改用StringBuilder),但不是相反。更具体地说,如果所有字符串都是编译时常量(字符串文字),它会做得更好——计算字符串文字并用它替换连接,这样运行时的开销就会更少。仅供参考 Oliver Charlesworth已经回答了您的问题,但我认为您在开始这个问题时选择了错误的位置 您应该使用
javap-vyouclass.class
检查字节码,而不是使用IDE检查反编译的代码,因为反编译的代码可能会非常混乱
原始java代码
public class LockElimination {
private static String concat(String s1, String s2, String s3) {
return s1 + s2 + s3;
}
}
由javap-v LockElimination.class生成的字节码
Constant pool:
#1 = Methodref #7.#16 // java/lang/Object."<init>":()V
#2 = Class #17 // java/lang/StringBuilder
#3 = Methodref #2.#16 // java/lang/StringBuilder."<init>":()V
#4 = Methodref #2.#18 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#5 = Methodref #2.#19 // java/lang/StringBuilder.toString:()Ljava/lang/String;
常量池:
#1=Methodref#7.#16//java/lang/Object.“:()V
#2=类#17//java/lang/StringBuilder
#3=Methodref#2.#16//java/lang/StringBuilder。”“:()V
#4=Methodref#2.#18//java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#5=Methodref#2.#19//java/lang/StringBuilder.toString:()Ljava/lang/String;
你确定你已经反编译了类的正确版本吗?你看到的是反编译器试图变得聪明,而不是编译后的代码的实际外观。StringBuilder
对于常量字符串没有意义。如果我写字符串s=“a”+“b”+“c”代码>编译器使用javap-c
生成如下所示的行:0:ldc#2//String abc
。因此,它是智能的,常量字符串被“粘合”成一个字符串。这意味着我们可以“免费”使用+进行代码格式化,这一点非常重要。