在Java中,比较一个对象和一个常量值时,“==”是装箱还是拆箱?

In Java, does "==" Box or Unbox when comparing an object and a constant value?

比较 Integer 对象和常量值时,Java 是装箱还是拆箱 Integer 对象?

根据我的阅读,“==”是引用比较,因此可以合理地假设 Java 将常量框起来以执行对象之间的引用比较。然而,下面的测试代码似乎给出了矛盾的结果。

Integer v1 = 1000;
Integer v2 = 1000;
boolean b1 = v1 == 1000; //True.
boolean b2 = v1 == v2; //False. Proof that 1000 boxes to new object and is not fetched from cache.

那么在 Java 中如何使用 == 进行对象与常量值的比较?在这种情况下,运算符是否按值进行比较?

你所说的 "a constant value" 是一个 int 字面量,所以它的类型是 int.

JLS 15.21.1 说:

If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands.

在你的v1 == 1000测试中,1000是数值类型,v1可以转换为数值类型,所以进行二进制数值提升。

JLS 5.6.2(二进制数字提升)说:

If any operand is of a reference type, it is subjected to unboxing conversion

因此,Integer 操作数 - v1 - 被拆箱为 int 并执行两个 int 的比较。因此比较的结果是true.

当您比较两个引用类型时 - v1 == v2 - 不进行拆箱,只比较引用,如 JLS 15.21.3:

中所写

If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.

由于 1000 太大而无法被 Integer 缓存缓存,b1b2 不引用同一个实例,因此结果比较是 false.

整数池与字符串池相同,但如果整数对象在 -128 到 127 范围内,它会缓存值 因此,当您尝试将此 range 中的值分配给包装器对象时,boxing 操作将调用 Integer.valueOf 方法,然后它将 分配对池中已经 的对象的引用。

但是,如果您将此 范围 之外的值分配给包装器 reference 类型,Integer.valueOf 将为该值创建一个新的 Integer 对象。因此,比较值超出此范围的 Integer 对象的引用将为您提供 false

所以在你的情况下

Integer v1 = 1000;
Integer v2 = 1000;
boolean b1 = v1 == 1000; //True.
boolean b2 = v1 == v2; // out of range so it will false but if you use 127 instead of 1000 then it will true.

查看文档here