java字符串连接符号+解密

相信很多人和我一样,在刚开始编写java程序时,只要出现字符串连接的地方直接一个“+”,觉得简单,方便,省事。

后来随着编码越来越多,阅读的书籍也越来越广,开始知道,在一些环境下使用StringBuilder(jdk1.5之前是StringBuffer,StringBuffer是线程安全的,但是在普通情况下使用反而会导致性能急剧下降)的效率会比高,相信大家查阅资料都可以知道,java编译器经过编译后,把我们使用的+自动转化为StringBuilder;


如图所示,我们根据字节码工具,可以清楚的知道了我们的方法被转换为使用StringBuilder,既然编译器已经帮我们做了,为什么我们还需要自己去使用StringBuilder呢;

private String getStr1() {
    String a = "1";
    String b = "2";
    String c = "3";
    String d = "4";
    String f = "";
    f =  a + b + c + d;
    return f;
}

private String getStr2() {
    String a = "1";
    String b = "2";
    String c = "3";
    String d = "4";
    String f = "";
    b = a + b;
    c = b + c;
    f = c + d;
    return f;
}

大家看看如上代码,这两个方法效果一样么?答案肯定是一致的,那这两个方法性能一致么?

我们同样来看看这两个方法的字节码:

private getStr1()Ljava/lang/String;
   L0
    LINENUMBER 20 L0
    LDC "1"
    ASTORE 1
   L1
    LINENUMBER 21 L1
    LDC "2"
    ASTORE 2
   L2
    LINENUMBER 22 L2
    LDC "3"
    ASTORE 3
   L3
    LINENUMBER 23 L3
    LDC "4"
    ASTORE 4
   L4
    LINENUMBER 24 L4
    LDC ""
    ASTORE 5
   L5
    LINENUMBER 25 L5
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.<init> ()V
    ALOAD 1
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 3
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 4
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
    ASTORE 5
   L6
    LINENUMBER 26 L6
    ALOAD 5
    ARETURN
   L7
    LOCALVARIABLE this Lcom/hik/yuntest/StringTest; L0 L7 0
    LOCALVARIABLE a Ljava/lang/String; L1 L7 1
    LOCALVARIABLE b Ljava/lang/String; L2 L7 2
    LOCALVARIABLE c Ljava/lang/String; L3 L7 3
    LOCALVARIABLE d Ljava/lang/String; L4 L7 4
    LOCALVARIABLE f Ljava/lang/String; L5 L7 5
    MAXSTACK = 2
    MAXLOCALS = 6


  // access flags 0x2
  private getStr2()Ljava/lang/String;
   L0
    LINENUMBER 30 L0
    LDC "1"
    ASTORE 1
   L1
    LINENUMBER 31 L1
    LDC "2"
    ASTORE 2
   L2
    LINENUMBER 32 L2
    LDC "3"
    ASTORE 3
   L3
    LINENUMBER 33 L3
    LDC "4"
    ASTORE 4
   L4
    LINENUMBER 34 L4
    LDC ""
    ASTORE 5
   L5
    LINENUMBER 35 L5
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.<init> ()V
    ALOAD 1
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
    ASTORE 2
   L6
    LINENUMBER 36 L6
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.<init> ()V
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 3
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
    ASTORE 3
   L7
    LINENUMBER 37 L7
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.<init> ()V
    ALOAD 3
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 4
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
    ASTORE 5
   L8
    LINENUMBER 38 L8
    ALOAD 5
    ARETURN
   L9
    LOCALVARIABLE this Lcom/hik/yuntest/StringTest; L0 L9 0
    LOCALVARIABLE a Ljava/lang/String; L1 L9 1
    LOCALVARIABLE b Ljava/lang/String; L2 L9 2
    LOCALVARIABLE c Ljava/lang/String; L3 L9 3
    LOCALVARIABLE d Ljava/lang/String; L4 L9 4
    LOCALVARIABLE f Ljava/lang/String; L5 L9 5
    MAXSTACK = 2

    MAXLOCALS = 6

看到上面的字节码是不是晕了,放心我也看不懂,不过看看我标红的那几句话,同样的效果,同样使用+连接符,方法getStr1只new了一个StringBuilder,而getStr2却new了三个,说明getStr1与我们直接使用StringBuilder的方式是一模一样的,在同一个语句行使用+,它就会直接使用append将字符串追加进去,不产生新的对象,但是分行写,每段的“+”操作,都会产生一个新的对象,从而性能会损失掉,所以如果我们在循环里面拼接字符串,就不要使用“+”。实在是想使用“+”,尽量将语句放在一行解决,但是这样书法又不太美观,总之,一句话,在合适的地方使用“+”,如果你在乎你的性能

发布了6 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/tushuping/article/details/79726449