在Java中编译时是否完成了字符串实习?

时间:2015-04-26 14:55:28

标签: java string equality

我对string interning在Java中的工作原理感到困惑。我写的时候:

String a = "ABC";
String b = "ABC";

if (a==b)
    System.out.println("Equal");

编译器是否在编译时将字符串文字“ABC”存储到字符串常量池中?

这听起来不合逻辑,因为我认为字符串常量池是由JVM在运行时创建的,如果它是在编译时完成的,我不知道如何这样做,因为Java编译器甚至没有调用JVM。

如果它没有在编译时完成并且在运行时完成,那么为什么以下返回false(取自this answer)?

// But .substring() is invoked at runtime, generating distinct objects
"test" == "!test".substring(1) // --> false

如果在运行时完成,为什么JVM不能确定它们是相同的字符串?

我真的很困惑字符串实习如何在Java中工作以及Java字符串池的存储位置。

2 个答案:

答案 0 :(得分:19)

编译器将文字字符串放在类文件中(并且只有唯一的字符串,它会整合所有等效的文字);加载类文件时,JVM将这些字符串加载到字符串池中。

  

如果在运行时完成,那么为什么JVM不能确定它们是相同的String。

因为.substring返回的字符串尚未被中断,因此与字符串池中的等效"test"字符串不同。如果你实习,你会得到true

"test" == "!test".substring(1).intern() // true

§4.4 of the JLS§5.3 of the JVM spec部分看起来很相似。

要明确:在Java中比较字符串的正确方法是使用.equals方法或类似方法,而不是==。将==与字符串实例一起使用通常不正确。 (除非你正在了解事情被拘禁的时间和方式......)

答案 1 :(得分:0)

我检查了.class

String a = "ABC";
String b = "ABC";

并且发现其中只有一个“ABC”。那就是javac在编译时创建了一个相同字符串的常量。

但是如果2个或更多类具有相同的“ABC”常量,那么JVM会将它们放在字符串池中的相同位置