为什么这些是 ==而不是 'equals()'?

2022-09-01 20:19:46

我对Java对待的方式以及当涉及到和其他类型的数字时有点困惑。例如:==equals()intInteger

Integer X = 9000;
int x = 9000;
Short Y = 9000;
short y = 9000;
List<Boolean> results = new ArrayList<Boolean>();
// results.add(X == Y); DOES NOT COMPILE        1)
results.add(Y == 9000);                      // 2)
results.add(X == y);                         // 3)
results.add(X.equals(x));                    // 4)
results.add(X.equals(Y));                    // 5)
results.add(X.equals(y));                    // 6)
System.out.println(results);

输出(也许你应该先做你的猜测):

[true, true, true, false, false]
  1. 这不是预期的编译,是不同的对象。X == Y
  2. 我有点惊讶,因为9是默认的,并且考虑到1)甚至没有编译。请注意,您不能将 a 放入期望 a 的方法中,但在这里它们是相等的。Y == 9trueintintShort
  3. 这与两个原因相同,但似乎更糟。
  4. 这并不奇怪,自动装箱到 和 .xInteger
  5. 这并不奇怪,因为不同类中的对象不应该是 。equal()
  6. 什么?? 是 但是 是 ?不应该总是比 更严格吗?X == ytrueX.equals(y)false==equals()

如果有人能帮助我理解这一点,我将不胜感激。出于什么原因 == 和 equals() 会以这种方式表现?

编辑:我已将 9 更改为 9000,以表明此行为与从 -128 到 127 的整数的任何异常行为方式无关。

2编辑好吧,如果你认为你理解这些东西,你应该考虑以下几点,只是为了确保:

Integer X = 9000;
Integer Z = 9000;
short y = 9000;
List<Boolean> results = new ArrayList<Boolean>();
results.add(X == Z);                      // 1)
results.add(X == y);                      // 2)
results.add(X.equals(Z));                 // 3)
results.add(X.equals(y));                 // 4)
System.out.println(results);

输出:

[false, true, true, false]

原因,尽我所能理解:

  1. 不同的实例,如此不同。
  2. X取消装箱,然后相同的值,所以相等。
  3. 相同的值,如此相等。
  4. y不能框到一个所以不能相等。Integer

答案 1

(小)整数实例被缓存,因此对于小型实例,固定的 x == y 被保留(实际上 -127 +128,取决于 JVM):

Integer a = 10;
Integer b = 10;

assert(a == b); // ok, same instance reused

a = 1024;
b = 1024;

assert(a == b); // fail, not the same instance....
assert(a.equals(b)); // but same _value_

编辑

4) 和 5) 产生 false,因为检查类型:是整数,而短整型。这是 java.lang.Integer#equals 方法:equalsXY

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }

    return false;
}

答案 2

原因

X == y

为真与二进制数字提升有关。当相等运算符的至少一个操作数可转换为数值类型时,将使用数值相等运算符。首先,第一个操作数已取消装箱。然后,将两个操作数转换为 。int

X.equals(y)

是正常的函数调用。如前所述,将自动装箱到对象。 如果参数不是实例,则始终返回 false。通过检查实现,可以很容易地看到这一点。yShortInteger.equalsInteger

有人可能会说这是一个设计缺陷。


推荐