String str = “abc“ + new String(“def“);到底创建了多少个对象?

题目如下:
下面main方法输出是什么?

public static void main(String[] args) {
        String str = "abc" + "def";
        String str2 = "abcdef";
        String str3 = "abc" + new String("def");
        String str4 = new String("abc") + new String("def");
        String str5 = new String("abcdef");
        System.out.println(str==str2);
        System.out.println(str==str3);
        System.out.println(str2==str3);
        System.out.println(str==str4);
        System.out.println(str==str5);
        System.out.println(str3==str4);
        System.out.println(str4==str5);
        System.out.println(str2==str5);
    }

先放答案:
true
false
false
false
false
false
false
false

惊不惊喜意不意外,接下来解释原因。
话不多说,先javac一下,再javap一下,反解析出汇编码文件:
 

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String abcdef
       2: astore_1
       3: ldc           #2                  // String abcdef
       5: astore_2
       6: new           #3                  // class java/lang/StringBuilder
       9: dup
      10: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      13: ldc           #5                  // String abc
      15: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      18: new           #7                  // class java/lang/String
      21: dup
      22: ldc           #8                  // String def
      24: invokespecial #9                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
      27: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      30: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      33: astore_3
      34: new           #3                  // class java/lang/StringBuilder
      37: dup
      38: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      41: new           #7                  // class java/lang/String
      44: dup
      45: ldc           #5                  // String abc
      47: invokespecial #9                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
      50: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      53: new           #7                  // class java/lang/String
      56: dup
      57: ldc           #8                  // String def
      59: invokespecial #9                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
      62: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      65: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      68: astore        4
      70: new           #7                  // class java/lang/String
      73: dup
      74: ldc           #2                  // String abcdef
      76: invokespecial #9                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
      79: astore        5
      81: getstatic     #11                 // Field java/lang/System.out:Ljava/io/PrintStream;
      84: aload_1
      85: aload_2
      86: if_acmpne     93
      89: iconst_1
      90: goto          94
      93: iconst_0
      94: invokevirtual #12                 // Method java/io/PrintStream.println:(Z)V
      97: getstatic     #11                 // Field java/lang/System.out:Ljava/io/PrintStream;
     100: aload_1
     101: aload_3
     102: if_acmpne     109
     105: iconst_1
     106: goto          110
     109: iconst_0
     110: invokevirtual #12                 // Method java/io/PrintStream.println:(Z)V
     113: getstatic     #11                 // Field java/lang/System.out:Ljava/io/PrintStream;
     116: aload_2
     117: aload_3
     118: if_acmpne     125
     121: iconst_1
     122: goto          126
     125: iconst_0
     126: invokevirtual #12                 // Method java/io/PrintStream.println:(Z)V
     129: getstatic     #11                 // Field java/lang/System.out:Ljava/io/PrintStream;
     132: aload_1
     133: aload         4
     135: if_acmpne     142
     138: iconst_1
     139: goto          143
     142: iconst_0
     143: invokevirtual #12                 // Method java/io/PrintStream.println:(Z)V
     146: getstatic     #11                 // Field java/lang/System.out:Ljava/io/PrintStream;
     149: aload_1
     150: aload         5
     152: if_acmpne     159
     155: iconst_1
     156: goto          160
     159: iconst_0
     160: invokevirtual #12                 // Method java/io/PrintStream.println:(Z)V
     163: getstatic     #11                 // Field java/lang/System.out:Ljava/io/PrintStream;
     166: aload_3
     167: aload         4
     169: if_acmpne     176
     172: iconst_1
     173: goto          177
     176: iconst_0
     177: invokevirtual #12                 // Method java/io/PrintStream.println:(Z)V
     180: getstatic     #11                 // Field java/lang/System.out:Ljava/io/PrintStream;
     183: aload         4
     185: aload         5
     187: if_acmpne     194
     190: iconst_1
     191: goto          195
     194: iconst_0
     195: invokevirtual #12                 // Method java/io/PrintStream.println:(Z)V
     198: return

接下来依次对每行java代码进行解析:

  • String str = "abc" + "def";
    面试最常问的最基本问题,指令如下:

    即+操作被jvm优化,为常量池中创建abcdef,并赋值给引用
    共计一个对象
    字符串常量的“+”号连接Java虚拟机会在程序编译期将其优化为连接后的值。

  • String str2 = "abcdef";
    同上,
    即常量池中创建abcdef,并赋值给引用
    共计一个对象

  • String str5 = new String("abcdef");

    这应该更容易理解,就是先创建了string对象,后在常量池创建abcdef,并使用常量池中的字符串构建string对象。
     共计创建了2个对象

  • String str3 = "abc" + new String("def");

    1.先创建一个StringBuilder对象
    2.常量池中创建abc
    3.StringBuilder对象调用append方法拼接abc
    4.创建String对象
    5.常量池中创建def,并使用常量池中的def构建String对象
    6.StringBuilder对象调用append方法拼接
    7.StringBuilder对象调用toString方法转成String,toString代码如下,实际上StringBuilder.toString()方法实际上调用的是 public String(char value[], int offset, int count) 构造方法,即使用char数组又创建了一个String对象。
    共计创建了5个对象。

  • String str4 = new String("abc") + new String("def");

    1.先创建一个StringBuilder对象
    2.创建String对象
    3.常量池中创建abc,并使用常量池中的abc构建String对象
    4.StringBuilder对象调用append方法拼接abc
    5.创建String对象
    6.常量池中创建def,并使用常量池中的def构建String对象
    7.StringBuilder对象调用append方法拼接
    8.StringBuilder对象调用toString方法转成String,toString代码逻辑同上,实际上StringBuilder.toString()方法实际上调用的是 public String(char value[], int offset, int count) 构造方法,即使用char数组又创建了一个String对象。 
    共计创建了6个对象


    所以只有直接引用常量池中的字符串的str与str2使用==相同,其他一律不同。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凡凡轶崔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值