使用 equals() 将包装器 class 与原语进行比较会产生奇怪的行为

Comparing wrapper class with primitive using equals() gives strange behavior

考虑下面的代码快照。 我们使用 equals() 来比较对象是否有意义? 这里两个值有意义地相等,但为什么 longWrapper.equals(0) return false 呢? 当我将两个值与 == 运算符进行比较时,它 returns true.

    Long longWrapper = 0L;
    long longPrimitive = 0;

    System.out.println(longWrapper == 0L); // true
    System.out.println(longWrapper == 0); //true
    System.out.println(longWrapper == longPrimitive); //true


    System.out.println(longWrapper.equals(0L)); //true
    System.out.println(longWrapper.equals(0));  //false
    System.out.println(longWrapper.equals(longPrimitive)); //true

这是因为 0 不是 long - 它是 int,包装器不会将整数转换为长整数

longWrapper.equals(0) returns false,因为 0 被自动装箱到 Integer,而不是 Long。由于两种类型不同,.equals() returns false.

同时,longWrapper == 0true,因为longwrapper值被拆箱为0,而0 == 0没有考虑实际的基本类型.

我想是因为equals方法中的0是Integer。当你用 0 定义 longPrimitive 时,这个 0 被转换为长值。 equals 方法接受所有对象,因此 0 保持为整数并且不会被强制转换。我的猜测是,如果给定对象是 long 的实例,则在 equals 方法中有一个调用,因为这个 0 是一个 Integer,它会导致 false。 希望对您有所帮助

当您比较 0 == 0L 时,您是在比较 int 文字和 long 文字。 int 得到 promotedlong,然后比较它们的值。由于两者均为零,因此结果为 true.

当您将自动装箱添加到组合中时,情况会略有不同。基元总是自动装箱为其包装器类型。在这里,0,它是一个 int 文字,被自动装箱到一个 java.lang.Integer 包装器实例。由于java.lang.Longjava.lang.Integer不同类,equals之间必须returnfalse.

这个:

System.out.println(longWrapper == 0);

正在与 == 进行比较,因此它会拆箱您的 Long,并且您正在比较两个基元,它们都是零。

这个:

System.out.println(longWrapper.equals(0));

正在与 equals 进行比较,因此它将 (int) 零作为 IntegerLong 对象永远不会等于 Integer 对象,即使它们拥有相同的数字。

Long的equals方法解释了为什么

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/lang/Long.java#Long.equals%28java.lang.Object%29

那里有线

 if (obj instanceof Long) {

longWrapper.equals(0) 参数将变为 Integer 类型。

另一方面longWrapper.equals(longPrimitive)会将参数装箱成Long

来自 Long.java class:

public boolean equals(Object obj) {
    if (obj instanceof Long) {
        return value == ((Long)obj).longValue();
    }
    return false;
}

因此,当您使用等号比较 Longint 时,if 条件失败并且方法 returns false.

其他方法return true 由于autoboxing and unboxing

System.out.println(0L == 0)True

所以 longWrapper == 0 拆箱后的结果是 True

并在 Long.equals 中写为 -

781     public boolean More ...equals(Object obj) {
782         if (obj instanceof Long) {
783             return value == ((Long)obj).longValue();
784         }
785         return false;
786     }

所以 System.out.println(longWrapper.equals(0)); return false 因为 0 将装在 Integer 中并且 if (obj instanceof Long) 是 false。