关于Java的字符串池的问题

and*_*and 68 java string string-pool

考虑以下代码:

String first = "abc"; 
String second = new String("abc");
Run Code Online (Sandbox Code Playgroud)

使用new关键字时,Java会abc String再次创建吗?这会存储在常规堆还是String池中?多少人String在将s结尾String池?

Jes*_*per 95

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

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

String s = "abc";
String p = "abc";
Run Code Online (Sandbox Code Playgroud)

那么Java编译器足够聪明,使只有一个String对象,s并且p将两者指的是同一个String对象.如果你这样做:

String s = new String("abc");
Run Code Online (Sandbox Code Playgroud)

然后String池中将有一个对象,即表示文字的对象"abc",并且将有一个单独的String对象,而不是池中的对象,它包含池化对象内容的副本.因为String在Java中是不可变的,所以你不会通过这样做获得任何东西; 调用new String("literal")在Java中永远不会有意义,并且不必要地低效.

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

另见String interning(维基百科).

  • @Tom在Java 7更新6中改变了实现细节.现在,当你调用`"someExtremelyExtremelyLongStringLiteral".substring(0,1)`时,分配一个新的,1个字符的`char []`,子串是完全的独立于原始文字.在`String`,`StringBuilder`等之间不再有任何`char []`共享.所以,继续前进,确实没有充分的理由使用`new String(String)` (4认同)
  • @Jesper:我想要明确一些事情.`new String("literal")`就像你说的那样没有意义,但我希望你不是在暗示调用"new String(someString)"没有意义并且不必要地效率低下.想象一下,你有`String s ="someExtremelyExtremelyLongStringLiteral";`.然后你会想要使用`String sub = new String(s.substring(0,1));`而不是`String sub = s.substring(0,1);`因为后一个版本会浪费内存.原因是当引用`s`消失时,仍然会有一个引用`sub`指向巨大的底层`char []`所以它不能被GC'ed (2认同)

dfa*_*dfa 12

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

  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位置),而第二个将存储在堆中.

编辑

由于将CONSTANT_String_info 索引存储为U2(16位,无符号),因此池可以包含max 2**16= 65535references.在这种情况下,您关心JVM的更多限制.

  • 查看字节码是一种很好的(并且被忽视的)方法,可以找出程序正在做什么. (2认同)

lou*_*imo 7

每次代码创建一个字符串文字

例如:

String str="Hello"; (string literal) 
Run Code Online (Sandbox Code Playgroud)

JVM首先检查字符串文字池.如果池中已存在该字符串,则返回对池化实例的引用.如果池中不存在该字符串,则新的String对象将实例化,然后放入池中.Java可以进行此优化,因为字符串是不可变的,可以共享而不用担心数据损坏