Java 整数在 .equals() 时总是 == 吗?

Are Java Integers always == when they're .equals()?

通常情况下,Java 库中对象的引用不能使用 == 进行比较,但我刚刚检查过:

Integer x = 5;
Integer y = x + 1;
Integer z = y - 1;
x.equals(z)
true   (boolean)
x == z
true   (boolean)

这只是我的 IDE 的产物,还是 Java Integer 对象在具有相同值时保证指向相同的 Integer?后一种保证会简化我正在编写的一些代码。

不总是,但在特定范围内。

这里要注意的是 Java 会捕获 -128 到 127 范围内的整数值。因此当您执行 ==

时它们 return 为真

这是相同的语言规范

http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7

If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.

我记得这样做的原因是为了在小型设备上实现性能。

Are Java Integers always == when they're .equals()?

没有。在正常情况下,尝试进行数值比较时不能依赖 ==Integer 实例。为此,您必须在比较之前将它们拆箱到 int,或者使用 equals.

您在示例中看到的事实是 JDK 缓存并重复使用有限数量的 Integer 实例(Integers 代表 -128 到 127)。来自 Integer.valueOf(int):

This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.

现在,您的代码正在使用装箱转换而不是 Integer.valueOf,并且装箱转换使用 Integer.valueOf 的规范 doesn't say,但很可能这正是它们所做的(实际上;例如,装箱转换和 Integer.valueOf 使用相同的底层机制和缓存)。

如果您使用不同的值,您可以看到 == 对于 Integer 个实例不可靠:(live copy)

Integer x = 524;    // <==== Changed
Integer y = x + 1;
Integer z = y - 1;
System.out.println("equals? " + x.equals(z));
System.out.println("==? " + (x == z));

输出(可能,这是我在 IDEOne 上得到的,但文档再次说 Integer 可能 缓存其他值):

equals? true
==? false

不,不能保证。对于某些值(尤其是较小的、更常用的值),该值将被内部化,并且将重用相同的对象引用。如果您尝试使用 3,279,831 进行相同的测试,它可能会 return false。