【问题标题】:JVM architecture: Runtime constant pool in Method area is per-classJVM 架构:Method 区域中的运行时常量池是 per-class
【发布时间】:2016-11-16 19:21:33
【问题描述】:

通过阅读Oracle JVM架构文档:

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html

运行时常量池是每个类或每个接口的运行时 类文件中 constant_pool 表的表示(第 4.4 节)。

我知道对于每个,它都有一个运行时常量池(如果我错了,请纠正我)。

但是,我感到困惑的是,如果我有两个不同的类 A 和 B,并且每个类都有一个私有字符串变量,比如 String value = "abc"

如果我使用== 而不是equals 比较A.valueB.value,我会得到一个true,这让我认为A 和B 中的"abc" 在同一个运行时常量池中?有人能指出我错在哪里吗?

【问题讨论】:

  • 你能链接文档吗?
  • @JigarJoshi 链接
  • 如果它们都是私有的,你如何同时访问它们来比较它们?是否创建另一个实例?你能发布你的完整代码吗?
  • 离题:为什么要使用==比较字符串?
  • @Andrew 我在 main 中为两个类创建实例并使用 getter 获取值。

标签: java jvm


【解决方案1】:

这是 JLS 叠加的抢先优化。

来自JLS 7, §3.10.5(格式化我的)

此外,字符串字面量总是指代String 类的同一个实例。这是因为字符串字面量 - 或者更一般地说,作为常量表达式 (§15.28) 的值的字符串 - 是“内部”的,以便使用 String.intern 方法共享唯一实例。

但是,请注意,这仅适用于字符串文字和常量表达式。动态构造的字符串(例如,x + y 用于字符串 xy)不会自动实习以共享相同的唯一实例。因此,除非您可以保证您的操作数是常量表达式,否则您仍然必须使用 .equals

【讨论】:

    【解决方案2】:

    这是因为 '==' 是在比较引用。 A 和 B 的对象都有不同的 String 值变量(因此每个类的常量池都有一个单独的条目);但它们都被初始化为相同的值。编译器/JVM 最有可能通过让它们都指向字节码中相同的编译时常量值来优化空间。 '==' 运算符不比较常量池位置。

    编辑:为了澄清一些混淆,这并不意味着“==”可以用于字符串比较。我只是说它也不能用于比较常量池位置。它是为了一件事,而且只是为了一件事:比较两个引用是否指向同一个对象。问题中的情况有时会导致 == 返回 true,但有时不会。这取决于编译器和 JVM 做出的决定(或者取决于 JSL 所说的作为一个精明的回答者所说的)。

    【讨论】:

    • 这是否意味着使用“==”进行字符串比较总是安全的?
    • @GuifanLi NO! "==" 运算符比较两个引用是否指向相同的值。如果程序从文件中读取字符串“abc”,则指向它的任何变量都不会 == 这个值。但是它们将是 .equal 的。
    猜你喜欢
    • 2022-01-17
    • 2014-05-20
    • 1970-01-01
    • 2014-06-01
    • 2016-08-22
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多