我知道String文本和新String对象之间的区别,也知道它在内部是如何工作的。但我的问题稍微提前了一点。当我们使用新关键字作为创建String对象时
String str = new String("test");
在本例中,我们将传递一个String类型的参数。我的问题是这个字符串是在哪里生成的——堆或字符串常量池还是其他地方?
据我所知,这个参数是一个字符串文字,所以它应该在字符串常量池中。如果是这样的话,那么intern
方法有什么用——只将变量str
链接到常量池?因为CCD_ 3将已经可用。
如果我误解了这个概念,请澄清一下。
语句String str = new String("test");
创建一个字符串对象,该对象与其他对象一样存储在堆中。作为参数传递的字符串文字"test"
存储在字符串常量池中。
String#intern()
检查字符串池中是否已有可用的字符串常量。如果已经有一个,它会返回它,否则它会创建一个新的并将其存储在池中。请参阅Javadocs:
返回字符串对象的规范表示形式。
最初为空的字符串池由类
String
私有维护。调用intern方法时,如果池中已经包含一个由
equals(Object)
方法确定的等于此string对象的字符串,则返回池中的字符串。否则,此String
对象将添加到池中,并返回对此String
对象的引用。由此可知,对于任意两个字符串
s
和t
,当且仅当s.equals(t)
为真时,s.intern() == t.intern()
为真。
从JDK7开始,中间的字符串存储在堆中。这来自JDK7:的发行说明
在JDK7中,中间字符串不再分配在Java堆的永久生成中,而是分配在Java堆栈的主要部分(称为年轻一代和老一代)以及应用程序创建的其他对象中。这种更改将导致更多的数据驻留在主Java堆中,而永久生成中的数据更少,因此可能需要调整堆大小。由于这一变化,大多数应用程序在堆使用方面只会看到相对较小的差异,但加载许多类或大量使用
String.intern()
方法的大型应用程序会看到更显著的差异。
intern()
:的使用
public static void main(String[] args) throws IOException {
String s = new String(new char[] { 'a', 'b', 'c' }); // "abc" will not be added to String constants pool.
System.out.println(System.identityHashCode(s));
s = s.intern();// add s to String constants pool
System.out.println(System.identityHashCode(s));
String str1 = new String("hello");
String str2 = "hello";
String str3 = str1.intern();
System.out.println(System.identityHashCode(str1));
System.out.println(System.identityHashCode(str2));
System.out.println(System.identityHashCode(str3));
}
O/p:
1414159026
1569228633 --> OOPs String moved to String constants pool
778966024
1021653256
1021653256 --> "hello" already added to string pool. So intern does not add it again.