String和StringBuffer
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