通过阅读Oracle JVM体系结构文档:
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html
运行时常量池是每个类或每个接口的运行时 在类文件中表示constant_pool表(第4.4节)。
我理解,对于每个类,它都有一个运行时常量池(如果我错了,请纠正我)。
然而,我感到困惑的是,如果我有两个不同的类A和B,并且每个类都有一个私有String变量,请说String value = "abc"
。
如果我使用A.value
而不是B.value
将==
与equals
进行比较,我会得到一个true
让我认为"abc"
A和B都在同一个运行时常量池中?有人能指出我错在哪里吗?
答案 0 :(得分:3)
这是JLS叠加的抢先优化。
来自JLS 7, §3.10.5(格式化我的)
此外,字符串文字始终引用类
String
的同一实例。这是因为字符串文字 - 或者更一般地说,字符串是常量表达式(§15.28)的值 - 是" interned"以便使用String.intern
方法共享唯一实例。
但请注意,这仅适用于字符串文字和常量表达式。动态构造的字符串(例如,x + y
和x
的{{1}}不会自动实现,以共享相同的唯一实例。因此,除非您可以保证操作数是常量表达式,否则您仍然必须使用y
。
答案 1 :(得分:1)
这是因为' =='是比较参考。 A和B的对象都有不同的String值变量(因此每个类'常量池都有一个单独的条目);但它们都被初始化为相同的值。编译器/ JVM很可能通过使它们都指向字节码中的相同编译时常量值来优化空间。 ' =='运算符不是比较常量池位置。
编辑:为了消除一些困惑,这并不意味着" =="可用于字符串比较。我所说的只是它不能用于比较常量池位置。这只是一件事,一件事:比较两个引用是否指向同一个对象。问题中的情况有时会导致==返回true,但有时不会。这取决于编译器和JVM做出的决定(或者取决于JSL作为精明的回答者所说的内容)。