在Java中比较两个原语与两个Object时,==实际上是相同还是不同? [英] Does == actually work the same or different when comparing two primitives vs two Objects in Java?

查看:100
本文介绍了在Java中比较两个原语与两个Object时,==实际上是相同还是不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在寻找有关逻辑等式 == 在Java中如何工作的解释时,答案总是类似于以下内容:

When searching for explanations of how logical equals == works in Java the answers are always something along the lines of:

  • 对于基元,它返回基元是否具有相同的值(这包括将基元与其WrapperObject进行比较,因为WrapperObject会自动取消装箱至基元).
  • 对于对象,它返回它们是否代表堆上的相同对象.

但是这些解释似乎都暗示它们是 2种不同的事物 == 的行为取决于您是否要比较对象还是原始.在我看来,它们实际上必须是完全相同的东西:从堆栈中获取两个变量并比较它们的值.

But these explanations all seem to imply that these are 2 different things, that == behaves differently depending whether you're comparing Objects vs primitives. It seems to me that they must actually be the exact same thing: Take two variables from the Stack and compare their values.

发生变化的不是 == 的行为,而是它所比较的​​值所代表的含义.如果您要比较的东西是基元,那么堆栈上的值就是基元本身的值.如果要比较对象,则堆栈上的值就是引用的值(因此就是堆上对象的地址).

The thing that changes isn't the behavior of ==, it's what the values it's comparing represent. If the things you're comparing are primitives then the value on the Stack is the value of the primitive itself. If you're comparing Objects then the value on the Stack is the value of the reference (and thus the address of the Object on the Heap).

我是否误解了,还是 == 在所有情况下实际上都表现相同?奖励积分是,如果您可以指向我了解如何在幕后真正发挥作用的文档.

Have I mis-understood something, or does == actually behave the same in all situations? Bonus points if you can point me to documentation on how this really works under the covers.

推荐答案

正如其他答案/注释所述,在Java语言级别上, == 运算符语义是指定的(在 JLS 15.21 中)以独立于实现的方式.严格来说,您不能从JLS文本中推断幕后"实现的详细信息.您可以说的是,任何 == 的一致实现都必须以某种方式 .

As other answers / comments say, at the Java language level the == operator semantics are specified (in JLS 15.21) in an implementation independent way. Strictly speaking, you cannot infer the "under the hood" implementation details from the JLS text. All that you can say is that any conformant implementation of == must behave in a certain way.

我将假设我们在谈论常规JVM,其中引用的实际机器表示是机器地址.可以通过其他方式实现引用.例如使用某种间接寻址机制,例如

I will assume that we are talking about conventional JVMs where the actual machine representation of a reference is a machine address. It is possible to implement references in other ways; e.g using some kind of indirect addressing mechanism such as a PIDLAM.

在字节码级别,有许多不同的字节码指令根据类型( int long 或参考).但是,比较的语义相似.一旦字节码被验证为类型安全的,就可以在硬件级别进行 == 比较的目的,对整数和地址进行相同的处理.

At the bytecode level, there are a number of different bytecode instructions that implement the logic of == depending on the type (int, long or reference). However, the semantic of the comparisons are similar. Once the bytecodes have been verified as type-safe, integers and addresses can be handled the same for the purposes of == comparison at the hardware level.

在硬件(机器指令)级别, == 对于基本整数类型和非基本值都起作用.在这两种情况下,它将执行一条机器指令,该指令比较来自寄存器或存储器(堆或堆栈)的两个字".

At the hardware (machine instruction) level == works the same for primitive integral types and non-primitive values. In both cases it will be executing a machine instruction that compares two "words" taken from a register or from memory (heap or stack).

JLS为 float double 指定的 == 语义有些不同,因为特殊值(无穷大和非整数值)需要特殊对待.例如:NaN == NaN是 false .另请参阅IEEE 754浮点标准.

The JLS specified semantics of == for float and double are a bit different because the special values (infinities and not-a-number values) need special treatment. For example: NaN == NaN is false. See also the IEEE 754 floating point standard.

对此有不同的字节码,并且在硬件级别,所使用的指令与在整数和参考情况下使用的指令不同.(特殊值的处理通常在浮动硬件中进行.)

There are different bytecodes for this, and at the hardware level the instructions used are different to those used in the integer and reference cases. (The treatment of special values is typically handled in the floating hardware.)

JLS为 boolean byte short char 是将值提升为另一种类型( int long float double )他们.如果操作数具有不同(未装箱)类型,则在其他情况下也会发生升级.

The JLS specified semantics of == for boolean, byte, short and char is to promote the values to another type (int, long, float or double) before comparing them. Promotion also occurs with other cases if the operands have different (unboxed) types.

此外,如果将一个(但不是两个!)操作数装箱,则会发生拆箱.如果将两个操作数都装箱,则 == 是参考比较.

In addition, unboxing occurs if one (but not both!) of the operands is boxed. If both operands are boxed, then == is a reference comparison.

总结以上...

我是否误解了某些东西,或者==在所有情况下实际上都表现相同?

Have I mis-understood something, or does == actually behave the same in all situations?

否,如果您包括浮点类型以及基本扩展和拆箱的注意事项,则不会.

No it doesn't, if you include floating point types, and the considerations of primitive widening and unboxing.

如果您能给我介绍有关其在幕后的实际工作方式的文档,则请加分.

Bonus points if you can point me to documentation on how this really works under the covers.

对此没有任何官方(Oracle)公共文档.JLS和JVM规范没有规定实现策略.

There is no official (Oracle) public documentation for this. The JLS and JVM spec do not prescribe implementation strategies.

这篇关于在Java中比较两个原语与两个Object时,==实际上是相同还是不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆