字符串比较解析

字符串比较

现有以下代码,需要分析其结果

String s0 = "red";
String s1 = "re";
String s2 = "d";
String s3 = s1 + s2;
System.out.println(s0 == ("re" + "d"));//1
System.out.println(s0 == s3);//2

结果如下:

true
false

为什么会这样呢?接下来我们一一分析

  • 对于 s0 == (“re” + “d”) 来说,由于"re" "d" 都是字符串常量,所以在Java编译时就会进行自动优化,将其合并为**“red”**

    • 方式1:我们将代码编译后生成的.class文件打开,就可以发现

      之前的

      System.out.println(s0 == ("re" + "d"));
      

      已经被优化为

      System.out.println(s0 == "red");
      
    • 方式2: 也可以使用反汇编来查看详细过程

       public static void main(java.lang.String[]);
          Code:
             0: ldc           #2                  // String red
             2: astore_1
             3: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
             6: aload_1
             7: ldc           #2                  // String red
             9: if_acmpne     16
            12: iconst_1
            13: goto          17
            16: iconst_0
            17: invokevirtual #4                  // Method java/io/PrintStream.println:(Z)V
            20: return
      }
      

      我们可以发现,在编译时第7行时就将字符串常量拼接成了 red。

因此,最后由于使用 == 比较**(地址比较)**,且比较的是同一个字符串 red ,其在字符串常量池中只会存储了一份,所以一定是同一个,结果为true。

  • 对于 s0 == s3

    public static void main(java.lang.String[]);
        Code:
           0: ldc           #2                  // String red
           2: astore_1
           3: ldc           #3                  // String re
           5: astore_2
           6: ldc           #4                  // String d
           8: astore_3
           9: new           #5                  // class java/lang/StringBuilder
          12: dup
          13: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
          16: aload_2
          17: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          20: aload_3
          21: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          24: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          27: astore        4
          29: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
          32: aload_1
          33: aload         4
          35: if_acmpne     42
          38: iconst_1
          39: goto          43
          42: iconst_0
          43: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
          46: return
    }
    
    

    通过反汇编我们可以发现,其s3=s1+s2在拼接时,底层调用了StringBuilder.append()方法,最终又调用toString()转为字符串对象,内存布局如下,所以s3中保存的是StringBuilder对象的地址,所以s0==s3结果为false.

    image-20210927202631413

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值