我有以下代码:
StringBuilder str = new StringBuilder("foo");
for(Field f : fields){
str.append("|" + f);
}
str.append("|" + bar);
String result = str.toString();
我知道编译器将优化字符串连接"|" + f
,并将其替换为StringBuilder。但是,将创建一个新的StringBuilder,还是在Java8中使用现有的str
?Java 9怎么样?
发布于 2017-07-26 10:57:40
发布于 2017-07-26 11:10:10
当字符串连接优化由Java编译器执行时,您可以通过解压缩字节代码来了解它所做的事情:
$ cat Test.java
interface Field {}
public class Test {
static String toString(Field[] fields, Object bar) {
StringBuilder str = new StringBuilder("foo");
for(Field f : fields){
str.append("|" + f);
}
str.append("|" + bar);
return str.toString();
}
}
$ javac Test.java
$ javap -c Test.class
Compiled from "Test.java"
public class stackoverflow.Test {
public stackoverflow.Test();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
static java.lang.String toString(stackoverflow.Field[], java.lang.Object);
Code:
0: new #16 // class java/lang/StringBuilder
3: dup
4: ldc #18 // String foo
6: invokespecial #20 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
9: astore_2
10: aload_0
11: dup
12: astore 6
14: arraylength
15: istore 5
17: iconst_0
18: istore 4
20: goto 53
23: aload 6
25: iload 4
27: aaload
28: astore_3
29: aload_2
30: new #16 // class java/lang/StringBuilder
33: dup
34: ldc #23 // String |
36: invokespecial #20 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
39: aload_3
40: invokevirtual #25 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
43: invokevirtual #29 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
46: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
49: pop
50: iinc 4, 1
53: iload 4
55: iload 5
57: if_icmplt 23
60: aload_2
61: new #16 // class java/lang/StringBuilder
64: dup
65: ldc #23 // String |
67: invokespecial #20 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
70: aload_1
71: invokevirtual #25 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
74: invokevirtual #29 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
77: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
80: pop
81: aload_2
82: invokevirtual #29 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
85: areturn
}
如您所见,代码在StringBuilder 3 places中调用构造函数(Method java/lang/StringBuilder."<init>":
),因此将在每次迭代中创建新的StringBuilders (除非实时编译器执行奇特的优化)。
这不太可能是一个显著的性能问题,但在不太可能的情况下,您可以很容易地通过重写到
str.append("|").append(f);
发布于 2017-07-26 11:32:35
根据Java9API文档
实现注意事项: 只要编译器最终符合Java规范,字符串连接操作符的实现将由Java编译器自行决定。例如,javac编译器可能使用StringBuffer、StringBuilder或java.lang.invoke.StringConcatFactory实现操作符,这取决于JDK版本。字符串转换的实现通常是通过toString方法实现的,该方法由对象定义,并由Java的所有类继承。
根据这一点,它将在每次迭代时创建一个新的字符串生成器。因此,正如这里的几个人所提到的,使用下面的代码是更优化的
append("|").append(f)
您可以找到API文档here。
https://stackoverflow.com/questions/45324692
复制相似问题