为什么这些==但不是`equals()`?

Eri*_*son 22 java equals

我对Java的方式对待有点混乱==,并equals()当它涉及到int,Integer和其他类型的数字.例如:

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);
Run Code Online (Sandbox Code Playgroud)

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

[true, true, true, false, false]
Run Code Online (Sandbox Code Playgroud)
  1. X == Y不能编译是可以预料的,是不同的对象.
  2. 我有点惊讶的Y == 9true,鉴于9是默认的int,并且鉴于1)甚至没有编译.请注意,你不能把int一个方法放入期望a的方法中Short,但在这里它们是相同的.
  3. 出于与两个相同的原因,这是令人惊讶的,但似乎更糟.
  4. 并不奇怪,因为自动x装箱和Integer.
  5. 不足为奇,因为不同类中的对象不应该equal().
  6. 什么?? X == ytrue,但是X.equals(y)false?不应该==总是比更严格equals()吗?

如果有人能帮助我理解这一点,我会很感激.出于什么原因,==和equals()表现如此?

编辑: 我已将9更改为9000以显示此行为与-128到127之间的整数表现的任何异常方式无关.

2 编辑: OK,如果你认为你明白这东西,你应该考虑以下内容,只是为了确保:

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);
Run Code Online (Sandbox Code Playgroud)

输出:

[false, true, true, false]
Run Code Online (Sandbox Code Playgroud)

我理解的原因是:

  1. 不同的实例,如此不同.
  2. X unboxed,然后相同的值,如此相等.
  3. 相同的价值,如此平等.
  4. y不能盒装到一个Integer所以不能平等.

dfa*_*dfa 22

(小)整数实例被缓存,因此不变的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_
Run Code Online (Sandbox Code Playgroud)

编辑

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

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

    return false;
}
Run Code Online (Sandbox Code Playgroud)


wax*_*ing 12

的原因

X == y
Run Code Online (Sandbox Code Playgroud)

真实与二进制数字促销有关.当等于运算符的至少一个操作数可转换为数字类型时,将使用数字相等运算符.首先,第一个操作数是未装箱的.然后,两个操作数都转换为int.

X.equals(y)
Run Code Online (Sandbox Code Playgroud)

是一个正常的函数调用.如上所述,y将自动装箱到一个Short物体.Integer.equals如果参数不是Integer实例,则始终返回false .通过检查实现可以很容易地看出这一点.

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


Mic*_*rdt 7

这个故事的士气:

自动装箱/拆箱令人困惑,类型促销也是如此.它们共同构成了良好的谜语,但却是可怕的代码.

在实践中,使用小于int的数字类型很少有意义,我几乎倾向于配置我的eclipse编译器将所有自动装箱和-unboxing标记为错误.