"" vs' new String(" a")' vs' new String(" a")。intern()'在字符串常量池中(JDK 6)

时间:2015-12-23 17:10:08

标签: java string jvm

我曾经知道以下两个语句在运行时在常量池中创建字符串a

String s = "a"
String s = new String("a")

在JVM上测试这些时,两种情况下的permgen大小都相同。

但是,以下代码段的行为与此不同:

String s2 = null;
for (int i = 0; i < 100; i++)
{
    s2 = s2 + i;
}

使用.intern(),permgen大小在每次迭代中增加:

String s2 = null;
for (int i = 0; i < 100; i++)
{
    s2 = s2 + i;
    s2.intern();
}

为什么这种行为是可观察的? s2.intern()是否向池中添加条目?这与这些声明有何不同?

String s = "a"
String s = new String("a")

2 个答案:

答案 0 :(得分:4)

这里有一点解释:

  • "a"在实习池中创建字符串“a”(如果尚未存在)
  • new String("a")因为参数是“a”,所以在实习池中创建字符串“a”(如果尚未存在)和副本“a”的内容是从实习池
  • 创建的
  • 取任何字符串s s.intern()返回该字符串的实习副本(如果存在于实习池中)。如果没有将该字符串添加到实习池中并返回新副本。

intern()方法的参考:

  

当调用实习方法时,如果池已包含   字符串等于此字符串对象由equals(Object)确定   方法,然后返回池中的字符串。否则,这个   String对象被添加到池中以及对此String的引用   返回对象。

注意:要创建String不要将其添加到实习池,您可以使用字符数组作为参数字符串构造函数

char[] helloArray = { 'h', 'e', 'l', 'l', 'o', '.' };
String helloString = new String(helloArray);

以下是对jls的引用,其中解释了字符串文本在字符串的实习池中出现:

  

字符串文字是对String类实例的引用(§4.3.1,§4.3.3)。

     

此外,字符串文字总是指同一个类的实例   串。这是因为字符串文字 - 或者更常见的是字符串   这是常量表达式的值(§15.28) - 是“实习”   以便使用String.intern。方法共享唯一的实例。

这是对最后评论的逐步解释:

// Creates the string "123", add it to the intern pool and assign "123" to s
String s = "123";  

// s.intern() returns the intern string of s. Because s is already the 
// string "123" present in the intern pool s and s.intern() are the same
System.out.println(s == s.intern());// true 

// "123" is already in intern pool. new String("123") create a new String
// that equals "123" but it is a different object
String s2 = new String("123"); 

// It prints false because s2 is equals to "123", but not the same object
// because a new String was created in the preciding row
System.out.println(s2 == s);// false

// It prints true because s2.intern() returns the string present in the
// intern pool that is equals to s2. That string exists and is "123"
System.out.println(s2.intern() == s);  // true

附加说明:对于每个等于s2的字符串s,s.intern()== s2.intern(),如果s == s2返回false。

// If s equals s2 but are not the same
if (s.equals(s2) && s != s2) {
    // THe intern string of s and s2 are always the same
    System.out.println(s.intern() == s2.intern()); // prints always true
}

答案 1 :(得分:0)

由于Interned Strings是在JVM范围内实现的,因此它们必须静态实现,这需要使用 class 属性进行缓存,这将消耗permgen内存。