【问题标题】:Is string interning done at compile time in Java? [duplicate]字符串实习是否在 Java 的编译时完成? [复制]
【发布时间】:2015-04-26 14:55:28
【问题描述】:

我真的很困惑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 字符串池的确切存储位置,我感到非常困惑。

【问题讨论】:

  • 以下链接有见地:stackoverflow.com/questions/513832/…
  • 我不确定你问题的第一部分,但substring 返回一个 new 对象,因此两个字符串的内容都匹配test ,因为它们不是同一个对象 == 返回 false。
  • 这是编译器。我不明白你为什么说它不能同时将字符串放入字符串常量池中。编译器会将常量字符串放在某个内存位置,然后在启动程序时,JVM 会加载该内存并创建常量池以在运行时使用,但该池是由编译器设置的。
  • 在 Stack Overflow 推出 6 年多之后,这怎么不是重复的?

标签: java string equality


【解决方案1】:

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

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

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

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

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


要明确一点:在 Java 中比较字符串的正确方法是使用 .equals 方法或类似方法,而不是 ==。将== 与字符串实例一起使用通常是不正确的。 (除非你想了解事物何时以及如何被拘留......)

【讨论】:

  • 子字符串@docs.oracle.com/javase/7/docs/api/java/lang/… 的文档特别声明它返回一个new 字符串对象。
  • 只是添加一些细节。很好的答案。
  • @RobertBain:intern 不是免费的,它需要付费。调用者可能不 A) 想要性能开销,和/或 B) 不希望返回的字符串在池中。我当然不想每次创建子字符串时都在表中查找内容,也不想将创建的每个临时子字符串都放入池中。
  • @T.J.Crowder 感谢您的详细解释 :)
  • @Kramer786:池存储对字符串的引用,这些引用是以通常方式存储的普通对象。池的目的纯粹是为了避免拥有多个等效字符串的副本,它不会将它们放在内存中的其他位置。关于它是如何找到它们的,实现细节就是这样,因此可能因 JVM 而异,但它可能使用 B-tree 或散列机制或类似机制。
【解决方案2】:

我检查了.class

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

并在其中仅找到一个“ABC”。即 javac 在编译时创建一个相同字符串的常量。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 2013-07-14
    • 2012-05-21
    • 2018-10-21
    • 2015-01-28
    • 1970-01-01
    • 2013-12-02
    • 2015-09-11
    相关资源
    最近更新 更多