在JAVA6中,编译器会始终对字符串的累加操作做优化编译。
编译器将字符串累加编译成StringBuilder。
源代码 |
String aa = "aa";
String bb = "bb";
String cc = "cc";
String result = aa + bb + cc;
编译后 |
NEW StringBuilder
DUP
ALOAD 1: aa
INVOKESTATIC String.valueOf(Object) : String
INVOKESPECIAL StringBuilder.<init>(String) : void
ALOAD 2: bb
INVOKEVIRTUAL StringBuilder.append(String) : StringBuilder
ALOAD 3: cc
INVOKEVIRTUAL StringBuilder.append(String) : StringBuilder
INVOKEVIRTUAL StringBuilder.toString() : String
ASTORE 4: result
编译器将字符串累加编译成一个字符串
源代码 |
String s="aa"+"bb"+"cc";
编译后 |
LDC "aabbcc"
最佳实践:先拼接字符串再拼接变量
从上可知第二种字符串累加的效率更高。
aa + "bb"+"cc" 效率小于 "bb"+"cc"+aa。
因为"bb"+"cc"会先编译为"bbcc"。而aa + "bb" + "cc"中出现变量,
在变量后的字符串就会编译成StringBuilder。
源代码 |
String aa = "aa";
String result3 = aa + "bb"+"cc";
String result4 = "bb"+"cc"+aa;
编译后 |
L0 (0)
LDC "aa"
ASTORE 1: aa
L1 (3)
NEW StringBuilder
DUP
ALOAD 1: aa
INVOKESTATIC String.valueOf(Object) : String
INVOKESPECIAL StringBuilder.<init>(String) : void
LDC "bb"
INVOKEVIRTUAL StringBuilder.append(String) : StringBuilder
LDC "cc"
INVOKEVIRTUAL StringBuilder.append(String) : StringBuilder
INVOKEVIRTUAL StringBuilder.toString() : String
ASTORE 2: result3
L2 (15)
NEW StringBuilder
DUP
LDC "bbcc"
INVOKESPECIAL StringBuilder.<init>(String) : void
ALOAD 1: aa
INVOKEVIRTUAL StringBuilder.append(String) : StringBuilder
INVOKEVIRTUAL StringBuilder.toString() : String
ASTORE 3: result4
L3 (24)
RETURN
L4 (26)
最佳实践:在循环中不要使用累加操作
因为StringBuilder是在循环内创建的。建议手动在外面创建StringBuilder。
StringBuilder eqPhone = new StringBuilder();
// 将#转换为-
for (String phoneNum : wwPhone.split("#")) {
if (StringUtil.isNotBlank(phoneNum)) {
eqPhone.append(phoneNum).append("-");
}
}
源代码:
public static void a()
{
String s1="1";
for (int i = 0; i <10; i++) {
s1+="2";
}
}
字节码:
public static void a();
0 ldc <String "1"> [56]
2 astore_0 [s1]
3 iconst_0
4 istore_1 [i]
5 goto 31
8 new java.lang.StringBuilder [54] //在循环里创建对象
11 dup
12 aload_0 [s1]
13 invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [77]
16 invokespecial java.lang.StringBuilder(java.lang.String) [58]
19 ldc <String "2"> [69]
21 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [61]
24 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [65]
27 astore_0 [s1]
28 iinc 1 1 [i]
31 iload_1 [i]
32 bipush 10
34 if_icmplt 8 //跳转到第8行
37 return
分析工具java asm