2024-03-14  阅读(3)
版权声明:本文为博主付费文章,严禁任何形式的转载和摘抄,维权必究。 本文链接:https://www.skjava.com/mianshi/baodian/detail/1831835548

回答

1 个或者 2 个。

  • 1 个:若字符串常量池中已经存在了 "abc" 这个值,则只会在 Java 堆上创建 1 个对象。
  • 2 个:若字符串常量池中没有 "abc" 这个值,则会创建 2 个对象,一个是字符串常量池中的对象,一个是 Java 堆上的。

详解

字符串常量池是这篇文章的基础,关于字符串常量池请先阅读这篇文章:

你是如何理解常量池的?

我们先看这个代码:

public class StringTest {
    public static void main(String[] args) {
        String str = new String("abc");
    }
}

我们先编译,然后利用 javap -verbose StringTest 查看结果:

public class com.skjava.demo.skjavademo.java.jichu.StringTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#15         // java/lang/Object."<init>":()V
   #2 = Class              #16            // java/lang/String
   #3 = String             #17            // abc
   #4 = Methodref          #2.#18         // java/lang/String."<init>":(Ljava/lang/String;)V
   #5 = Class              #19            // com/skjava/demo/skjavademo/java/jichu/StringTest
   #6 = Class              #20            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               SourceFile
  #14 = Utf8               StringTest.java
  #15 = NameAndType        #7:#8          // "<init>":()V
  #16 = Utf8               java/lang/String
  #17 = Utf8               abc
  #18 = NameAndType        #7:#21         // "<init>":(Ljava/lang/String;)V
  #19 = Utf8               com/skjava/demo/skjavademo/java/jichu/StringTest
  #20 = Utf8               java/lang/Object
  #21 = Utf8               (Ljava/lang/String;)V
{
  public com.skjava.demo.skjavademo.java.jichu.StringTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=1
         0: new           #2                  // class java/lang/String
         3: dup
         4: ldc           #3                  // String abc
         6: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
         9: astore_1
        10: return
      LineNumberTable:
        line 5: 0
        line 6: 10
}

我们关注这部分内容:

  • 0: new #2:创建一个新的 String 对象。#2 是对常量池的引用,指向Class #16 // java/lang/String,表明正在创建的是String类的一个实例。
0: new           #2                  // class java/lang/String

#2 = Class              #16            // java/lang/String
#16 = Utf8               java/lang/String

  • 4: ldc #3 :将一个常量("abc")从常量池中推送至栈顶。#3是对常量池中String #17 // abc的引用,表示将字面量 "abc" 加载到操作栈上。