Java String + 拼接空字符串性能问题

开发过程中,遇到的问题,特此记录一下,也想着分享出来,免得不了解的朋友疑惑。

我们都知道 java String + 底层是通过一个 StringBuilder 实现的拼接,但当需要拼接的两个 String 常量,有一个 String 为空字符串(即:"")时,那会不会是一种特殊情况呢?带着这个疑问,我们去看下下面小实验,

首先创建了一个TestDemo类,代码如下:

public class TestDemo{
    String a;
    String x = "Anthony";

    public TestDemo(){}

    public void test1() {
        if (true){
            a = x;
        } else {
            a = "" + x;
        }
    }

    public void test2() {
        if (false){
            a = x;
        } else {
            a = "" + x;
        }
    }

    public void test3() {
        if (false){
            a = x;
        } else {
            a = "Cidy" + x;
        }
    }
}

通过javac、javap命令编译一下,查看下cpu会执行到的指令,
test1() 函数指令:

public void test1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: aload_0
         2: getfield      #3                  // Field x:Ljava/lang/String;
         5: putfield      #4                  // Field a:Ljava/lang/String;
         8: return
      LineNumberTable:
        line 10: 0
        line 14: 8

test2() 函数指令:

public void test2();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=1, args_size=1
         0: aload_0
         1: new           #5                  // class java/lang/StringBuilder
         4: dup
         5: invokespecial #6                  // Method java/lang/StringBuilder."":()V
         8: ldc           #7                  // String
        10: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        13: aload_0
        14: getfield      #3                  // Field x:Ljava/lang/String;
        17: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        20: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        23: putfield      #4                  // Field a:Ljava/lang/String;
        26: return
      LineNumberTable:
        line 20: 0
        line 22: 26

test3() 函数指令:

public void test3();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=1, args_size=1
         0: aload_0
         1: new           #5                  // class java/lang/StringBuilder
         4: dup
         5: invokespecial #6                  // Method java/lang/StringBuilder."":()V
         8: ldc           #10                 // String Cidy
        10: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        13: aload_0
        14: getfield      #3                  // Field x:Ljava/lang/String;
        17: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        20: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        23: putfield      #4                  // Field a:Ljava/lang/String;
        26: return
      LineNumberTable:
        line 28: 0
        line 30: 26

对 test1 和 test2 指令比较

test1()与test2()指令比较

它们的比较,主要区别在于执行了“+”操作后,会创建 StringBuilder 对象,这个时候会增加内存的开销;

对 test2 和 test3 指令比较

test2()与test3()指令比较

它们的比较,主要想看空字符串与非空字符串对内存的影响。整体来看,除了创建的 String 字符串占用的字节数不同外,其他的完全相同;

综合以上内容,我们了解到只要执行 String + 操作,底层就会创建一个 StringBBuilder 对象来处理字符串的拼接。所以当我们在开发的过程中,尽量避免空字符串执行 String + 拼接操作。

你可能感兴趣的:(Java String + 拼接空字符串性能问题)