下面是String.intern()方法的Javadoc注释:
*返回字符串对象的规范表示形式。
字符串池(最初为空)由类字符串私下维护。
当调用intern方法时,如果池中已经包含了一个与这个字符串对象相等的字符串,则返回来自这个池的字符串。否则,将此字符串对象添加到池中,并返回对此字符串对象的引用。
因此,对于任意两个字符串s和t,s.intern() == t.intern()是真当且仅当s.equals(t)为真。
所有文字字符串和字符串值常量表达式都是内嵌的。字符串文字在Java规范第3.10.5节中定义。“
,但我认为是一些东西改变了jdk-8u102以前的.
请查看下面的示例:
public class Test1 {
public static void main(String[] args) {
String s1 = new String(new char[]{'J', 'a', 'v', 'a'});
String s2 = s1.intern();
System.out.println(s1 == s2);
}
}如果您在JDK 7u80 ( JDK 7的最后一个稳定版本)和JDK 8到8u101中运行上述程序,那么输出是:
真
但是,如果您在JDK 8u102和JDK 9& JDK 10中运行上述程序,则输出是:
假
为什么intern()方法开始有不同的行为方式?
我检查了发行说明和Javadoc注释,但没有发现与JDK8u102中的intern()方法相关的任何更改。
我查过博客和其他网站,但没有运气。
但是,当我尝试使用其他字符串时,输出没有变化:
public class Test2 {
public static void main(String[] args) {
String s3 = new String(new char[]{'U', 'd', 'a', 'y', 'a', 'n'});
String s4 = s3.intern();
System.out.println(s3 == s4);
}
}上面的程序总是在JDK 7、JDK 8、JDK 9和JDK 10中打印真。
只有当字符串池表在加载Test1类之前引用“Java”时,才有可能出现这种行为。
s1引用堆上的字符串对象“Java”,s1.intern()返回String对象的引用(因为字符串池已经引用了“Java”)。
这就是为什么s1 == s2返回false的原因。
但是,当加载Test2类时,String表不引用“Udayan”。
s3引用堆上的String对象“Udayan”,s3.intern()将s3引用的String对象添加到String中,并返回相同的引用。这意味着s3和s4引用同一个对象。
这就是为什么s3 == s4返回true的原因。
如果我的观察是正确的,那么这意味着字符串池最初并不是空的。
字符串池最初包含“java”、“java”、“Oracle”和其他字符串对象。
有人能确认一下吗?
发布于 2018-04-24 11:24:31
这取决于你认为什么是“最初”。
JVM启动时,字符串池为空。但是,当在加载Test1类之前加载和初始化各种基本JDK类时,其中一些类将Strings添加到String中就不足为奇了。"Java“必须是这些String之一。
JLS没有阻止Java开发人员在更新的JDK版本的类初始化中引入新的String文字。因此,您注意到JDK 7和JDK 8之间的差异并不奇怪。
https://stackoverflow.com/questions/50000370
复制相似问题