"Java14字符串常量池问题及解析"

需积分: 0 0 下载量 7 浏览量 更新于2023-12-20 收藏 2.67MB PDF 举报
本人在Java 14的环境下测试了"尚硅谷面试题第三季1"中的Java基础部分。其中有一个关于字符串常量池的问题,代码如下: ```java public class StringPool58Demo { public static void main(String[] args) { String str1 = new StringBuilder("58").append("tongcheng").toString(); System.out.println(str1); System.out.println(str1.intern()); System.out.println(str1 == str1.intern()); System.out.println("---; } } ``` 在这段代码中,我们首先创建了一个新的字符串`str1`,其值为"58tongcheng"。接着我们调用`intern()`方法将`str1`添加到字符串常量池中,并打印出`str1`和`str1.intern()`的值。最后,我们使用`==`运算符比较`str1`和`str1.intern()`的地址。根据Java语言规范,`str1.intern()`返回的是字符串常量池中的引用,而`str1`则是在堆上创建的新对象,所以我们预期的结果是`str1 == str1.intern()`应该为`true`。 然而,在实际测试中,我们得到的结果却是`true`和`false`。这让我们感到困惑。经过仔细的分析和调试,我们发现了这个问题的根源。 首先,根据JDK7及以后的规定,当我们创建一个字符串时,如果该字符串常量池中不存在相同值的字符串,那么该字符串将被添加到常量池中。在这种情况下,我们通过`str1.intern()`方法得到的引用将会是常量池中已存在的引用,因此`str1 == str1.intern()`的比较结果确实应该是`true`。 然而,在我们的测试中,`str1 == str1.intern()`的结果却是`false`。这让我们开始怀疑,是否在加载`sun.misc.Version`类时,已经将`str1`的引用添加进了常量池。经过一番深入研究和分析,我们发现了问题所在。 在JDK自带的`System.java`类中,存在一个名为`Version`的内部静态类。在加载该类时,会触发`sun.misc.Version`的初始化操作,而在该初始化代码中存在一个与`str1`相关的字符串常量池操作。这就是导致`str1 == str1.intern()`结果为`false`的根本原因。 通过这个问题,我们深刻意识到了字符串常量池的运行机制以及在Java版本迭代中的变化,加深了我们对Java基础知识的理解。同时也对代码执行过程中的细微差别和底层机制有了更加深入的认识。这个问题的解决过程不仅让我们对Java的字符串常量池有了更加清晰的认识,也提醒我们在实际开发中要仔细分析问题的根源,善用调试工具,加深理解并学习底层实现原理。