给定下面的2个toString()实现,哪个是首选的:
public String toString(){
return "{a:"+ a + ", b:" + b + ", c: " + c +"}";
}
or
public String toString(){
StringBuilder sb = new StringBuilder(100);
return sb.append("{a:").append(a)
.append(", b:").append(b)
.append(", c:").append(c)
.append("}")
.toString();
}
?
更重要的是,鉴于我们只有3个属性,它可能不会有什么不同,但在什么时候你会从+ concat切换到StringBuilder?
值得一提的是,正如@ZhekaKozlov指出的那样,
自Java 9以来,+更快,除非JVM不知道如何优化它(例如,循环中的连接)。
我检查了以下代码的字节码(在Java 17中):
public class StringBM {
public String toStringPlus(String a) {
return "{a:" + a + ", b:" + ", c: " + "}";
}
public String toStringBuilder(String a) {
StringBuilder sb = new StringBuilder(100);
return sb.append("{a:").append(a)
.append(", b:")
.append(", c:")
.append("}")
.toString();
}
}
For toStringPlus:
0: aload_1
1: invokedynamic #7, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
6: areturn
for toStringBuilder:
0: new #11 // class java/lang/StringBuilder
3: dup
4: bipush 100
6: invokespecial #13 // Method java/lang/StringBuilder."<init>":(I)V
9: astore_2
10: aload_2
11: ldc #16 // String {a:
13: invokevirtual #18 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: aload_1
17: invokevirtual #18 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: ldc #22 // String , b:
22: invokevirtual #18 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
25: ldc #24 // String , c:
27: invokevirtual #18 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: ldc #26 // String }
32: invokevirtual #18 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
35: invokevirtual #28 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
38: areturn
+版本简单地调用动态函数makeConcatWithConstants和并传入方法参数{a:\u0001, b:, c:} (\u0001是参数占位符)。
而StringBuilder版本必须以“诚实”的方式来实现。
我想我们可以看到为什么+现在更快了。
我喜欢:
String.format( "{a: %s, b: %s, c: %s}", a, b, c );
...因为它简短易读。
我不会为速度而优化它,除非您在重复次数非常高的循环中使用它,并测量了性能差异。
我同意,如果必须输出大量参数,这个表单可能会令人困惑(就像其中一个评论所说的那样)。在这种情况下,我将切换到更可读的形式(可能使用apache-commons的ToStringBuilder -取自matt b的答案),并再次忽略性能。