当前位置: 首页 > 知识库问答 >
问题:

为什么String.intern()在JDK 8和JDK 9下返回不同的结果?

公羊新
2023-03-14

以下代码在使用JDK 8和JDK 9运行时有不同的结果。

public static void main(String[] args) {
    String s = new String("1");
    s.intern();
    String s2 = "1";
    System.out.println(s == s2);

    String s3 = new String("1") + new String("1");
    //String s3 = "1" + "1";
    s3.intern();
    String s4 = "11";
    System.out.println(s3 == s4);
    System.out.println(s3.equals(s4));
}

在JDK 8(版本1.8.0_172)下,代码打印:

false
true
true

但是使用JDK 9(版本9.0.1),代码返回:

false
false
true

我已经检查了两个JDK版本,它们是正确的。为什么代码会产生不同的结果?我的程序有什么问题吗?

共有2个答案

龙德义
2023-03-14

Eran的答案很接近。正如他所指出的,当字符串文字被插入时,关键问题是。

我有充分的证据表明,最近的一些JVM懒散地进行字符串文本的实习,而且这种实习发生在第一次运行时使用该文本之前。被告知这是新行为的人说。

所以实际的解释似乎是Java9是这种新的“懒惰”行为被引入的时候,这解释了Java8的区别

(我将尝试在OpenJDK源代码中查看这种情况发生的地方……)

钮实
2023-03-14

结果取决于String"11"在调用s3.intern()之前是否已经在String池中。

如果不是的话,s3。intern()s3添加到池中,并返回s3。在这种情况下,s4也将被分配“11”的规范表示,因为它是用字符串文字初始化的。因此,s3==s4将是true

如果是,s3。intern()将返回“11”的规范表示,它与s3的实例不同。因此,s3==s4将是false

我没有JDK9版本来测试您的代码,但如果这是您得到的输出,这意味着在您的main之前执行的JDK9源代码的某个地方,出现了“11”String文本,它将String添加到池中。

JDK8中并非如此。

在这两种情况下,使用“1”String的测试都会给出false,因为String“1”在新字符串(“1”)中传递给String构造函数时会添加到池中。因此,s.intern()不会将s引用的String添加到池中,并且String s2=“1”s是一个不同的实例。

当试图理解这种行为时,intern的Javadoc非常方便:

字符串java.lang.String.intern()

返回字符串对象的规范表示形式。

最初为空的字符串池由类字符串私下维护。

调用intern方法时,如果池中已经包含一个字符串,该字符串等于equals(object)方法确定的这个字符串对象,则返回池中的字符串。否则,此字符串对象将添加到池中,并返回对此字符串对象的引用。

...

所有文字字符串和字符串值常量表达式都是内部的。

 类似资料:
  • 问题内容: 为什么更改总和顺序会返回不同的结果? = = 双方的Java和JavaScript的返回相同的结果。 我知道,由于以二进制表示浮点数的方式,某些有理数( 例如1/3-0.333333 … )无法精确表示。 为什么简单地更改元素的顺序会影响结果? 问题答案: 也许这个问题很愚蠢,但是为什么仅仅改变元素的顺序会影响结果呢? 它将根据值的大小更改四舍五入的点。作为示例 _样的_事情,我们所看

  • 为什么改变求和顺序会返回不同的结果? = Java和JavaScript都返回相同的结果。 我知道,由于浮点数在二进制中的表示方式,一些有理数(如1/3-0.333333...)不能精确表示。 为什么简单地改变元素的顺序会影响结果?

  • 问题内容: 这是一个Java代码段: 而且它根据不同的JDK表现不同 在Oracle JDK 1.7中的输出是: 在OpenJDK 1.6中的输出也是: 但是在Oracle JDK 1.6中,输出为: 如此方法的JavaDoc所指示 输出: 应该可以预期,但是三个JDK都不会产生这种情况。以及Oracle JDK1.6为什么提供: 结果是? 我认为在OracleJDK 1.7和openJDK 1.

  • 问题内容: 在有人质疑使用的事实之前,我先说一下,出于内存和性能的原因,我需要在特定的应用程序中使用它。[1] 因此,到目前为止,我一直使用并假定这是最有效的方法。但是,自古以来我就注意到它是软件的瓶颈。[2] 然后,就在最近,我试图用一个巨大的映射替换,在该映射中放置/获取字符串,以便每次获得唯一的实例。我以为这会慢一些…但是事实恰恰相反!它快得多了!通过推送/轮询地图(实现完全相同)来替换,可

  • 当我执行普通Select时,返回正确的结果,但当我执行Select for DB uptime时,它始终返回相同的第一个结果。我确实检查了Postgres日志,我看到select被执行了。

  • 我有以下表格结构: 1-课程(course_id、course_nam、语言、course_price、create_date、average_rating、course_description、certifica_price、course_creator_id) 2-学生(学生证、钱包) 3-折扣(折扣id、折扣课程id、允许的许可课程id、开始日期、结束日期、百分比) 4-报名(student