关于 Java 字符串池的问题

2022-08-31 13:59:52

请考虑以下代码:

String first = "abc"; 
String second = new String("abc");

使用关键字时,Java会再次创建对吗?这是存储在常规堆上还是池中?池中将结束多少秒?newabcStringStringStringString


答案 1

如果使用关键字,将创建一个新对象。请注意,对象始终位于堆上 - 字符串池不是独立于堆的单独内存区域。newString

字符串池就像一个缓存。如果这样做:

String s = "abc";
String p = "abc";

然后Java编译器足够聪明,可以只创建一个对象,并且两者都引用相同的String对象。如果这样做:Stringsp

String s = new String("abc");

然后池中将有一个对象,表示文本的对象,并且将有一个单独的对象,不在池中,其中包含池中对象内容的副本。由于在Java中是不可变的,因此这样做不会获得任何好处;调用在Java中永远没有意义,并且不必要的低效。String"abc"StringStringnew String("literal")

请注意,您可以调用对象。如果对象尚不存在,这会将该对象放入池中,并返回对池化字符串的引用。(如果它已经在池中,它只返回对已经存在的对象的引用)。有关详细信息,请参阅该方法的 API 文档。intern()StringString

另见字符串实习(维基百科)。


答案 2

字节码中,第一个赋值为:

  Code:
   0:   ldc     #2; //String abc
   2:   astore_1

而第二个是:

   3:   new     #3; //class java/lang/String
   6:   dup
   7:   ldc     #2; //String abc
   9:   invokespecial   #4; //Method java/lang/String."":(Ljava/lang/String;)V

因此,第一个位于池中(位于位置 #2),而第二个将存储在堆中。

编辑

由于将索引存储为 U2(16 位,无符号),因此池可以包含 max = 引用。如果您在这里关心JVM的更多限制CONSTANT_String_info2**1665535