字符串池最初是否为空,如String.intern()方法的Javadoc中所述?

Uda*_*try 5 java string string-interning string-pool

下面是String.intern()方法的Javadoc注释:

*返回字符串对象的规范表示.

最初为空的字符串池由String类私有维护.

调用实习方法时,如果池已经包含等于此字符串对象的字符串(由equals(Object)方法确定),则返回池中的字符串.否则,将此String对象添加到池中,并返回对此String对象的引用.

因此,对于任何两个字符串s和t,当且仅当s.equals(t)为真时,s.intern()== t.intern()才为真.

所有文字字符串和字符串值常量表达式都是实体.字符串文字在The Java™Language Specification的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果在JDK 7u80(JDK 7的最后稳定版本)和JDK 8到8u101上运行以上程序,则输出为:
true

但是如果你在JDK 8u102以及JDK 9和JDK 10中运行以上程序,则输出为:
false

为什么intern()方法开始表现不同JDK 8u102以后?

我检查了发行说明和Javadoc注释,但在JDK 8u102中找不到与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);
    }
}
Run Code Online (Sandbox Code Playgroud)

以上程序始终在JDK 7,JDK 8,JDK 9和JDK 10中打印为true.

仅当在加载Test1类之前由String Pool表引用"Java"时,才会出现此行为.
s1引用HEAP上的String对象"Java",s1.intern()返回String Pool对象的引用(因为"Java"已经被字符串池引用).
这就是为什么s1 == s2返回false.

但是当加载Test2类时,字符串池表不会引用"Udayan".
s3引用HEAP上的String对象"Udayan",s3.intern()将s3引用的String对象添加到String Pool并返回相同的引用.这意味着s3和s4指的是同一个对象.
这就是为什么s3 == s4返回true.

如果我的观察是正确的,那么这意味着字符串池最初不是空的.
字符串池最初包含"Java","java","Oracle"和其他String对象.

任何人都可以确认一下吗?

Era*_*ran 9

这取决于你认为"最初".

JVM启动时,字符串池为空.但是,当在加载类之前加载和初始化各种基本JDK类时Test1,将其中一些添加String到字符串池并不奇怪."Java"必须是其中之一String.

JLS中没有任何内容阻止Java开发人员String在新JDK版本的类初始化中引入新文字.因此,您在JDK 7和JDK 8之间注意到的差异并不令人惊讶.