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

Kra*_*786 15 java string equality

我真的很困惑字符串实习在Java中是如何工作的.我写的时候:

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

if (a==b)
    System.out.println("Equal");
Run Code Online (Sandbox Code Playgroud)

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

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

如果它不是在编译时完成并且它是在运行时完成的,那么为什么以下返回false(取自此答案)?

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

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

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

T.J*_*der 19

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

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

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

"test" == "!test".substring(1).intern() // true
Run Code Online (Sandbox Code Playgroud)

JLS的4.4节和JVM规范的5.3节看起来很相关.


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

  • @RobertBain:"实习生"不是免费的,它带有成本.调用者可能不会A)想要性能开销,和/或B)不希望返回的字符串在池中.我当然不希望每次创建子字符串时都在表中查找内容,也不想将我创建的每个瞬态子字符串放入池中. (4认同)