Java 下面代码的equal方法解释

Java equal method explanation on the following code

我一直在 Java 上阅读一本名为 Thinking in Java 的书(我来自 C 语言背景)。我遇到了以下两组代码

  public class EqualsMethod {
      public static void main(String[] args) {
        Integer n1 = new Integer(47);
        Integer n2 = new Integer(47);
        System.out.println(n1.equals(n2));
      }
    } 
//Output: true

我理解这个相等的方法是比较引用。但是 n1 和 n2 是两个对象,驻留在'两个不同的 "bubble" 堆中。那怎么会相等呢?

另一个示例代码是

class Value {
  int i;
}

    public class EqualsMethod2 {
      public static void main(String[] args) {
        Value v1 = new Value();
        Value v2 = new Value();
        v1.i = v2.i = 100;
        System.out.println(v1.equals(v2));
      }
    } /* Output:false


}

为什么会报错?非常期待您的深入回答。谢谢。

因为你没有覆盖equals方法。如果您不覆盖它,那么它将检查引用是否相等,并相应地 return。

可以参考Integer class中定义的equals()方法。

System.out.println(n1.equals(n2)) // this prints true because it refers to Integer equals method.

同样,您必须为您的值 class 覆盖它。

class Value {
    int i;

    @Override
    public boolean equals(Object obj) {
        boolean returnValue = false;
        if (obj != null && obj instanceof Value) {
            Value valObj = (Value) obj;
            if (this.i == valObj.i) {
                returnValue = true;
            }
        }
        return returnValue;
    }
}

现在 System.out.println(v1.equals(v2)); 打印 true.

equals 在您的自定义 class 中的行为完全取决于您。如果覆盖它,则由您决定 class 的两个对象何时被视为彼此相等。如果你不覆盖它,你会得到 Object class 的默认实现,它检查两个引用是否引用同一个对象(即检查你的示例中是否 v1==v2,这是假)。

Integer 是有价值的类型。所以比较 Integer 变量通过比较它们的值来执行。在您的特定情况下它们是相等的。

比较两个对象(引用类型)通过比较不相等的引用来执行。

您可以通过在 class 中重载 equals() 方法来编写自己的比较逻辑。

I understand that this equal method is comparing the reference.

错了。在 Object class 中,此方法包含引用比较,但 Integer 有其自己的实现,它覆盖了 Object.

提供的实现

它比较两个整数的值,而不是它们的引用。

Integer 具有比较值的 equals() 方法,而您的 Value class 没有。它使值 class 与相等比较 "pointer",它们是不同的。

如果您在比较 class 中的属性 i 的 class 值中重写 equals 方法,它将 return 为真。 例如

public boolean equals(Object o){
   return (this.i == ((Value) o).i) ? true : false;
}

所有 Wrapper 类 中的 Equals 方法在 java 中默认被覆盖。这就是第一个片段起作用的原因。 对于您自己的 类,您必须提供 equals 方法的实现。

默认情况下,Java 中的 equal 方法检查两个对象引用是否相同。你可以 @Override 方法,然后做你想做的。所以得到False是正常的,因为两个Object是不一样的。

So how come they are equal?

整数 是一个对象。另一方面 int 是一个简单的类型。 Integer 的 equals() 方法在内部比较 int,因为它覆盖了 Object equals() 方法。 int 有相同的值。

Why does this give false?

您的 Value class 不会覆盖 equal 的方法,因此会比较引用,就像您编写 v1 == v2 时一样。在这种情况下,它们是不同的对象,所以它是错误的。

您好,您对 equals 和 == 的理解完全错误或与实际情况相反。

equals() 方法也像 == 一样检查引用,除非您覆盖 equals 方法,否则两者之间没有区别。 == 检查引用是否相等。为了更好地理解,请参阅对象 class 源代码。

 public boolean equals(Object obj) {
    return (this == obj);
}

为什么它适用于您的情况?是因为Integerclass覆盖了里面的equals方法

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

现在,当您使用自定义 class 检查相等性时,它所做的基本上就是调用。

v1==v2

它怎么能给你真实的?它们在堆中都有不同的内存位置。 如果仍然不清楚,请在您的代码中放置断点,然后 运行 将其置于调试模式。

问题根源:

您没有覆盖 eqauals 和 hashCode,然后 JVM 将新的 hashCode 分配给您在 Value class

的情况下创建的任何对象

=================

解决方案: 您将需要定义衡量价值对象身份的标准,即执行以下操作

1) 重写equals方法并指定对实例变量i的值进行相等性检查

2) 覆盖 Hashcode 并使用实例变量 i 进行 hashCode 比较

==在对象class的equals方法中使用,避免两个引用指向同一个对象时进行不必要的计算,否则继续计算比较

public 布尔等于(对象 anObject) {

if (this == anObject) {

return 正确;

} 否则{

  // Do the calculation here to check the identity check 

}