string,再看String

StringBuilder和StringBuffer的区别就不写了,就是一个木有加锁一个加了锁,这里只来看看String相加时jvm做的一些事情,来看一下是不是new一个StringBuilder来append就一定比字符两个字符串直接+要好。
通常来用的仅仅几个字符串的拼接这两种方式实际来说相差不大,不过如果在很多很多很多个字符串拼接的时候,相差是相当相当大的(亲身经历,哈哈)
jdk版本:
guanfei@guanfei-desktop:~/workspace/StudyTest/src/test$ java -version java version "1.6.0_20" Java(TM) SE Runtime Environment (build 1.6.0_20-b02) Java HotSpot(TM) Server VM (build 16.3-b01, mixed mode)

一. n个常量字符串相加

  • 源码:就是将多个常量字符串相加
private static final String str3 = "str3"; public String testStrAddStr() { String str1 = "str1" + "str2"+str3+"str4"; return str1; }
  • jvm进行的处理:直接把这些字符串拼好,当成一个常量处理。在这种情况下,要比new一个StringBuilder来一个一个的append相加要好的。
const #2 = String #36; // str1str2str3str4 注:常量池 public java.lang.String testStrAddStr(); Code: Stack=1, Locals=2, Args_size=1 0: ldc #2; //String str1str2str3str4 2: astore_1 3: aload_1 4: areturn LineNumberTable: line 8: 0 line 9: 3

二. 字符串常量和字符串变量相加

  • 源码:
public String testStrAddVar(String str) { String str1 = "str1" + str; return str1; }
  • jvm处理之后:实际上来说这种情况jvm处理后的结果和自己手动去写个StringBuilder是一样的,而且貌似直接写"str1" + str会更简洁一些。
public java.lang.String testStrAddVar(java.lang.String); Code: Stack=2, Locals=3, Args_size=2 0: new #3; //class java/lang/StringBuilder 3: dup 4: invokespecial #4; //Method java/lang/StringBuilder."":()V 7: ldc #5; //String str1 9: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 12: aload_1 13: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 16: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 19: astore_2 20: aload_2 21: areturn

三. 字符串变量和常量混合相加(在一行中连加)

  • 源码:
public String testMixAdd(String str1, String str2) { String str4 = str1 + "str1" + str2 + "str2"; return str4; }
  • jvm处理之后:同样,jvm自动处理为StringBuilder的append
public java.lang.String testMixAdd(java.lang.String, java.lang.String); Code: Stack=2, Locals=4, Args_size=3 0: new #3; //class java/lang/StringBuilder 3: dup 4: invokespecial #4; //Method java/lang/StringBuilder."":()V 7: aload_1 8: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 11: ldc #5; //String str1 13: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 16: aload_2 17: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 20: ldc #8; //String str2 22: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 25: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 28: astore_3 29: aload_3 30: areturn

四. 字符串变量和常量混合相加(在多行中分别相加)

  • 源码:
public String testAddAndAdd(String str1, String str2) { String str4 = str1 + "str1"; str4 = str4 + "str2"; str4 += str2; return str4; }
  • jvm处理之后:这个时候很明显的发现,jvm的"智商"不够用了,每一行相加的语句都会新创建一个StringBulder然后append,很明显,这个时候自己手动的去创建StringBuilder然后去append,要少很多对象的创建。
public java.lang.String testAddAndAdd(java.lang.String, java.lang.String); Code: Stack=2, Locals=4, Args_size=3 0: new #3; //class java/lang/StringBuilder 3: dup 4: invokespecial #4; //Method java/lang/StringBuilder."":()V 7: aload_1 8: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 11: ldc #5; //String str1 13: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 16: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 19: astore_3 20: new #3; //class java/lang/StringBuilder 23: dup 24: invokespecial #4; //Method java/lang/StringBuilder."":()V 27: aload_3 28: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 31: ldc #8; //String str2 33: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 36: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 39: astore_3 40: new #3; //class java/lang/StringBuilder 43: dup 44: invokespecial #4; //Method java/lang/StringBuilder."":()V 47: aload_3 48: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 51: aload_2 52: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 55: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 58: astore_3 59: aload_3 60: areturn

五. 循环中的字符串相加

  • 源码: public String testCycle() { String str = ""; for (int i = 0; i < 10; ++i) { str += i; } return str; }
  • jvm处理之后:很明显,循环内部每次都会新建StringBuilder对象,每次去toString,要浪费很多了。
public java.lang.String testCycle(); Code: Stack=2, Locals=3, Args_size=1 0: ldc #9; //String 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: bipush 10 8: if_icmpge 36 11: new #3; //class java/lang/StringBuilder 14: dup 15: invokespecial #4; //Method java/lang/StringBuilder."":()V 18: aload_1 19: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 22: iload_2 23: invokevirtual #10; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 26: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 29: astore_1 30: iinc 2, 1 33: goto 5 36: aload_1 37: areturn

结论

1. 对于一些常量字符串的拼接,直接"+"就好了。
2. 对于简单的几个字符串拼接,如:str1+str2+str3+"str4"之类的,直接用"+"也木有问题
3. 循环的大量的字符串拼接,一定手动构建StringBuilder来append
4. 大家一直在进步,包括jvm
Tags:  string类 string

延伸阅读

最新评论

发表评论