1:String对象的重载”+”操作
小例子:
public class TestString {
public static void main(String[] args){
String a="a";
String s="a"+"b"+"c"+1;
System.out.println("s: "+s);
}
}
查看字节码了解它是怎么工作的
(idea中如何查看字节码:参考博客:http://blog.csdn.net/qq_24489717/article/details/53837493)
public static void main(java.lang.String[]);
Code:
0: ldc #7 // String a
2: astore_1
3: ldc #8 // String abc1
5: astore_2
6: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
9: new #3 // class java/lang/StringBuilder
12: dup
13: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
16: ldc #10 // String s:
18: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: aload_2
22: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
25: invokevirtual #6 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
28: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
31: return
通过看字节码,编译器创建了一个StringBuilder对象,用它来构造最终的String
为每个字符串调用一次StringBuilder.append()方法,最后调用toString()方法生成结果并存为s
如果我们没有用for循环进行拼接字符串,是用String拼接还是用StringBuilder进行拼接都是一样的,因为编译器最后将String是用StringBuilder进行拼接的,但是用了for循环以后,虽然最后的结果是一样的,但是消耗的资源是不一样的
String使用for循环进行拼接字符串
static String testString(String[] fields){
String result="";
for(int i=0;i<fields.length;i++){
result+=fields[i];
}
return result;
}
字节码如下:
static java.lang.String testString(java.lang.String[]);
Code:
0: ldc #2 // String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: aload_0
7: arraylength
8: if_icmpge 38
11: new #3 // class java/lang/StringBuilder
14: dup
15: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
18: aload_1
19: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: aload_0
23: iload_2
24: aaload
25: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #6 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore_1
32: iinc 2, 1
35: goto 5
38: aload_1
39: areturn
第8行到第25行为一个for循环
可以看到每经过一个循环都要创建一个StringBuilder对象
StringBuilder使用for循环进行拼接字符串
字节码如下:
static java.lang.String testStringBuilder(java.lang.String[]);
Code:
0: new #3 // class java/lang/StringBuilder
3: dup
4: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
7: astore_1
8: iconst_0
9: istore_2
10: iload_2
11: aload_0
12: arraylength
13: if_icmpge 30
16: aload_1
17: aload_0
18: iload_2
19: aaload
20: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
23: pop
24: iinc 2, 1
27: goto 10
30: aload_1
31: invokevirtual #6 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
34: areturn
从13行到27行为一个for循环,StringBuilder对象的创建在for循环以外
所以若使用for循环拼接字符串,那么StringBuilder拼接字符串的开销比较小
之前和StringBuilder类似的是StringBuffer,StringBuffer是线程安全的,但是并不需要对String字符串进行线程安全,因为StringBuffer是线程安全的所以开销更大,在最新的java se引用了StringBuilder,现在用的也是StringBuilder而不是StringBuffer