StringBuilder和String“+”号拼接,哪个效率高呢

对于程序本身的优化,可以借鉴很多前辈们的经验,但是有些时候,

package com.evan.springboot.study;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

/**
 * @author evanYang
 * @version 1.0
 * @date 2020/4/17 上午 11:15
 */
public class TestStringAndStringBuild {
    public static void main(String[] args) {

    }

    public void m1(){
        String s1="123";
        String s2="456";
        String s3=s1+s2;
        System.out.println(s3);
    }
    
    public void m2(){
        String s1="123";
        String s2="456";
        StringBuilder sb = new StringBuilder();
        sb.append(s1);
        sb.append(s2);
        String S3 = sb.toString();
        System.out.println(S3);
    }
	
	 public void m3(){
        String str="";
        for (int i = 0; i < 5; i++) {
            str=str+i;
        }
        System.out.println(str);
    }
    
    public void m4(){
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 5; i++) {
            sb.append(i);
        }
        System.out.println(sb);
    }
}

这里是不是很多人都会觉得m2效率更快?真像真的是这样的吗? m3和m4方法哪个更快呢?让我们带着这两个问题一起来研究一下吧?

我们先进入到TestStringAndStringBuild 的class类目录
在这里插入图片描述
在执行以下命令

javap -v TestStringAndStringBuild.class > Ts.txt

我们能看到在D:\IdeaProject\springboot\target\classes\com\evan\springboot\study生成了Ts.txt文件
StringBuilder和String“+”号拼接,哪个效率高呢_第1张图片
打开Ts.txt文件

Classfile /D:/IdeaProject/springboot/target/classes/com/evan/springboot/study/TestStringAndStringBuild.class
  Last modified 2020-4-17; size 1731 bytes
  MD5 checksum df05b27a8ae3e481562d00a3bfce2dba
  Compiled from "TestStringAndStringBuild.java"
public class com.evan.springboot.study.TestStringAndStringBuild
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #19.#52        // java/lang/Object."":()V
   #2 = Class              #53            // com/evan/springboot/study/TestStringAndStringBuild
   #3 = Methodref          #2.#52         // com/evan/springboot/study/TestStringAndStringBuild."":()V
   #4 = Methodref          #2.#54         // com/evan/springboot/study/TestStringAndStringBuild.m1:()V
   #5 = Methodref          #2.#55         // com/evan/springboot/study/TestStringAndStringBuild.m2:()V
   #6 = Methodref          #2.#56         // com/evan/springboot/study/TestStringAndStringBuild.m3:()V
   #7 = Methodref          #2.#57         // com/evan/springboot/study/TestStringAndStringBuild.m4:()V
   #8 = String             #58            // 123
   #9 = String             #59            // 456
  #10 = Class              #60            // java/lang/StringBuilder
  #11 = Methodref          #10.#52        // java/lang/StringBuilder."":()V
  #12 = Methodref          #10.#61        // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #13 = Methodref          #10.#62        // java/lang/StringBuilder.toString:()Ljava/lang/String;
  #14 = Fieldref           #63.#64        // java/lang/System.out:Ljava/io/PrintStream;
  #15 = Methodref          #65.#66        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #16 = String             #67            //
  #17 = Methodref          #10.#68        // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
  #18 = Methodref          #65.#69        // java/io/PrintStream.println:(Ljava/lang/Object;)V
  #19 = Class              #70            // java/lang/Object
  #20 = Utf8               
  #21 = Utf8               ()V
  #22 = Utf8               Code
  #23 = Utf8               LineNumberTable
  #24 = Utf8               LocalVariableTable
  #25 = Utf8               this
  #26 = Utf8               Lcom/evan/springboot/study/TestStringAndStringBuild;
  #27 = Utf8               main
  #28 = Utf8               ([Ljava/lang/String;)V
  #29 = Utf8               args
  #30 = Utf8               [Ljava/lang/String;
  #31 = Utf8               ts
  #32 = Utf8               MethodParameters
  #33 = Utf8               m1
  #34 = Utf8               s1
  #35 = Utf8               Ljava/lang/String;
  #36 = Utf8               s2
  #37 = Utf8               s3
  #38 = Utf8               m2
  #39 = Utf8               sb
  #40 = Utf8               Ljava/lang/StringBuilder;
  #41 = Utf8               S3
  #42 = Utf8               m3
  #43 = Utf8               i
  #44 = Utf8               I
  #45 = Utf8               str
  #46 = Utf8               StackMapTable
  #47 = Class              #71            // java/lang/String
  #48 = Utf8               m4
  #49 = Class              #60            // java/lang/StringBuilder
  #50 = Utf8               SourceFile
  #51 = Utf8               TestStringAndStringBuild.java
  #52 = NameAndType        #20:#21        // "":()V
  #53 = Utf8               com/evan/springboot/study/TestStringAndStringBuild
  #54 = NameAndType        #33:#21        // m1:()V
  #55 = NameAndType        #38:#21        // m2:()V
  #56 = NameAndType        #42:#21        // m3:()V
  #57 = NameAndType        #48:#21        // m4:()V
  #58 = Utf8               123
  #59 = Utf8               456
  #60 = Utf8               java/lang/StringBuilder
  #61 = NameAndType        #72:#73        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #62 = NameAndType        #74:#75        // toString:()Ljava/lang/String;
  #63 = Class              #76            // java/lang/System
  #64 = NameAndType        #77:#78        // out:Ljava/io/PrintStream;
  #65 = Class              #79            // java/io/PrintStream
  #66 = NameAndType        #80:#81        // println:(Ljava/lang/String;)V
  #67 = Utf8
  #68 = NameAndType        #72:#82        // append:(I)Ljava/lang/StringBuilder;
  #69 = NameAndType        #80:#83        // println:(Ljava/lang/Object;)V
  #70 = Utf8               java/lang/Object
  #71 = Utf8               java/lang/String
  #72 = Utf8               append
  #73 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #74 = Utf8               toString
  #75 = Utf8               ()Ljava/lang/String;
  #76 = Utf8               java/lang/System
  #77 = Utf8               out
  #78 = Utf8               Ljava/io/PrintStream;
  #79 = Utf8               java/io/PrintStream
  #80 = Utf8               println
  #81 = Utf8               (Ljava/lang/String;)V
  #82 = Utf8               (I)Ljava/lang/StringBuilder;
  #83 = Utf8               (Ljava/lang/Object;)V
{
  public com.evan.springboot.study.TestStringAndStringBuild();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."":()V
         4: return
      LineNumberTable:
        line 10: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/evan/springboot/study/TestStringAndStringBuild;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class com/evan/springboot/study/TestStringAndStringBuild
         3: dup
         4: invokespecial #3                  // Method "":()V
         7: astore_1
         8: aload_1
         9: invokevirtual #4                  // Method m1:()V
        12: aload_1
        13: invokevirtual #5                  // Method m2:()V
        16: aload_1
        17: invokevirtual #6                  // Method m3:()V
        20: aload_1
        21: invokevirtual #7                  // Method m4:()V
        24: return
      LineNumberTable:
        line 12: 0
        line 13: 8
        line 14: 12
        line 15: 16
        line 16: 20
        line 17: 24
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      25     0  args   [Ljava/lang/String;
            8      17     1    ts   Lcom/evan/springboot/study/TestStringAndStringBuild;
    MethodParameters:
      Name                           Flags
      args

  public void m1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=1
         0: ldc           #8                  // String 123
         2: astore_1
         3: ldc           #9                  // String 456
         5: astore_2
         6: new           #10                 // class java/lang/StringBuilder
         9: dup
        10: invokespecial #11                 // Method java/lang/StringBuilder."":()V
        13: aload_1
        14: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        17: aload_2
        18: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        21: invokevirtual #13                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        24: astore_3
        25: getstatic     #14                 // Field java/lang/System.out:Ljava/io/PrintStream;
        28: aload_3
        29: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        32: return
      LineNumberTable:
        line 20: 0
        line 21: 3
        line 22: 6
        line 23: 25
        line 24: 32
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      33     0  this   Lcom/evan/springboot/study/TestStringAndStringBuild;
            3      30     1    s1   Ljava/lang/String;
            6      27     2    s2   Ljava/lang/String;
           25       8     3    s3   Ljava/lang/String;

  public void m2();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=1
         0: ldc           #8                  // String 123
         2: astore_1
         3: ldc           #9                  // String 456
         5: astore_2
         6: new           #10                 // class java/lang/StringBuilder
         9: dup
        10: invokespecial #11                 // Method java/lang/StringBuilder."":()V
        13: astore_3
        14: aload_3
        15: aload_1
        16: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        19: pop
        20: aload_3
        21: aload_2
        22: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        25: pop
        26: aload_3
        27: invokevirtual #13                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        30: astore        4
        32: getstatic     #14                 // Field java/lang/System.out:Ljava/io/PrintStream;
        35: aload         4
        37: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        40: return
      LineNumberTable:
        line 27: 0
        line 28: 3
        line 29: 6
        line 30: 14
        line 31: 20
        line 32: 26
        line 33: 32
        line 34: 40
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      41     0  this   Lcom/evan/springboot/study/TestStringAndStringBuild;
            3      38     1    s1   Ljava/lang/String;
            6      35     2    s2   Ljava/lang/String;
           14      27     3    sb   Ljava/lang/StringBuilder;
           32       9     4    S3   Ljava/lang/String;

  public void m3();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: ldc           #16                 // String
         2: astore_1
         3: iconst_0
         4: istore_2
         5: iload_2
         6: iconst_5
         7: if_icmpge     35
        10: new           #10                 // class java/lang/StringBuilder
        13: dup
        14: invokespecial #11                 // Method java/lang/StringBuilder."":()V
        17: aload_1
        18: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        21: iload_2
        22: invokevirtual #17                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        25: invokevirtual #13                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        28: astore_1
        29: iinc          2, 1
        32: goto          5
        35: getstatic     #14                 // Field java/lang/System.out:Ljava/io/PrintStream;
        38: aload_1
        39: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        42: return
      LineNumberTable:
        line 37: 0
        line 38: 3
        line 39: 10
        line 38: 29
        line 41: 35
        line 42: 42
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            5      30     2     i   I
            0      43     0  this   Lcom/evan/springboot/study/TestStringAndStringBuild;
            3      40     1   str   Ljava/lang/String;
      StackMapTable: number_of_entries = 2
        frame_type = 253 /* append */
          offset_delta = 5
          locals = [ class java/lang/String, int ]
        frame_type = 250 /* chop */
          offset_delta = 29

  public void m4();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: new           #10                 // class java/lang/StringBuilder
         3: dup
         4: invokespecial #11                 // Method java/lang/StringBuilder."":()V
         7: astore_1
         8: iconst_0
         9: istore_2
        10: iload_2
        11: iconst_5
        12: if_icmpge     27
        15: aload_1
        16: iload_2
        17: invokevirtual #17                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        20: pop
        21: iinc          2, 1
        24: goto          10
        27: getstatic     #14                 // Field java/lang/System.out:Ljava/io/PrintStream;
        30: aload_1
        31: invokevirtual #18                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        34: return
      LineNumberTable:
        line 45: 0
        line 46: 8
        line 47: 15
        line 46: 21
        line 49: 27
        line 50: 34
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           10      17     2     i   I
            0      35     0  this   Lcom/evan/springboot/study/TestStringAndStringBuild;
            8      27     1    sb   Ljava/lang/StringBuilder;
      StackMapTable: number_of_entries = 2
        frame_type = 253 /* append */
          offset_delta = 10
          locals = [ class java/lang/StringBuilder, int ]
        frame_type = 250 /* chop */
          offset_delta = 16
}
SourceFile: "TestStringAndStringBuild.java"

内容大致分为4部分:
第一部分:显示了生成这个class的java源文件,版本信息,生成时间等。
第二部分:显示了该类所涉及的常量池
第三部分:显示了该类的构造器,编译器自动插入的
第四部分:显示了main方法信息(这个是我们需要重点解读的)

常量池
Class: 类或接口的符号引用
Fieldref: 字段的符号引用
Methodref: 类中方法的符号引用
InterfaceMethodref: 接口中方法的符号引用
String: 字符串类型常量
Integer: 整形常量
Float: 浮点型常量
Long: 长整形常量
Double: 双进度浮点型常量
NameAndType: 字段或方法的符号引用
utf-8: UTF-8编码的字符串
MethodType: 标志方法类型
InvokeDynamic: 表示一个动态方法调用

字段描述符

FieldType Type interpretation
B byte
C char
D double
F float
I int
J long
LClassName reference
S short
Z boolean
[ reference one array dimension
         6: new           #10                 // class java/lang/StringBuilder
         9: dup
        10: invokespecial #11                 // Method java/lang/StringBuilder."":()V
        13: aload_1
        14: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        17: aload_2
        18: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        21: invokevirtual #13                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        24: astore_3
        25: getstatic     #14                 // Field java/lang/System.out:Ljava/io/PrintStream;
        28: aload_3
        29: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        32: return

从解字节码中可以看出,m1()方法源码中使用+号拼接,但是在字节码中也被编译成stringBuilder方式
所以可以得出结论,字符串拼接,+号和stringBuilder是相等的,效率一样

可以看到,m3()方法中的循环体内,每一次循环都会创建StringBuilder对象,效率低于 m4()方法。

你可能感兴趣的:(JVM)