4

在比较 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 中是如何工作的呢?在这种情况下,运算符是否按值进行比较?

4

2 回答 2

3

你所说的“常量值”是一个int文字,所以它的类型是int.

JLS 15.21.1说:

如果相等运算符的操作数都是数字类型,或者一个是数字类型而另一个是可转换(第 5.1.8 节)为数字类型,则对操作数执行二进制数字提升。

在您的v1 == 1000测试中,1000是数字类型并且v1可以转换为数字类型,因此执行二进制数字提升。

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

如果任何操作数是引用类型,则对其进行拆箱转换

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

当您比较两种引用类型时v1 == v2- 不会进行拆箱,仅比较引用,如JLS 15.21.3中所写:

如果相等运算符的操作数既是引用类型又是 null 类型,则该操作是对象相等。

由于1000太大而无法被缓存Integer缓存,b1并且b2没有引用同一个实例,因此比较的结果是false.

于 2020-03-04T06:44:57.833 回答
0

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

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

所以在你的情况下

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.

在此处查看文档

于 2020-03-04T06:52:09.273 回答