过年结束了,今天想温故下java的基础知识,突然想起当初遇到过的equals方法重写的问题,特此回忆记录下:
大多数的书,教材甚至在jdk上的equals重写代码都如下
@Override
public boolean equals(Object obj)
{
if(obj==this) return true;//quick check 短路检查
if(obj instanceof ClassX)
{
return ((ClassX)obj).getXX().equals(this.getXX());//属性比较
}
return false;
}
乍看下应该没有问题,其实很有问题。
Java API对于对象相等(object equals方法)定义的很详细,必须满足以下方面:
- 自反性:x.euqals(x);
- 对称性:x.equals(y), y.equals(x);
- 传递性:x.euqals(y),y.equals(z),z.equals(x);
- 一致性:在一致状态下,x.equals(y)总是返回一致状态;
- 能与null比较:null.equals(x);
而上述的代码恰恰会在对称性方面出现问题:
父类TestParent.java代码
@Override
public boolean equals(Object obj)
{
if(obj==this) return true;//quick check 短路检查
if(obj instanceof TestParent)
{
return ((TestParent)obj).getName()().equals(this.getName());//属性比较
}
return false;
}
子类TestSon.java代码
@Override
public boolean equals(Object obj)
{
if(obj==this) return true;//quick check 短路检查
if(obj instanceof TestSon)
{
return ((TestSon)obj).getName()().equals(this.getName());//属性比较
}
return false;
}
两个比较结果
TestParent p = new TestParent("xiaoxiao");
TestSon s = new TestSon("xiaoxiao", 11);
System.out.println(p.equals(s));//true
System.out.println(s.equals(p));//false
测试结果却是违反了对称性原则,检查代码发现其错误源于instanceof后面的类型比较。因此,在重写equals方法时,不应使用instanceof比较,而推荐利用getClass()来进行比较。
修改的TestParent.java代码
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj != null && this.getClass() != obj.getClass()) {
return false;
}
TestParent p = (TestParent) obj;
return p.getName().equals(this.name);
}
修改的TestSon.java代码
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj != null && obj.getClass() == getClass() && super.equals(obj)) {
TestSon son = (TestSon) obj;
return son.getAge() == this.getAge();
}
return false;
}
这样,原有的测试则都打印false,不过这样的比较也有缺点,在于其无法应用于比较不同类,但是逻辑意义上相等的情况,不过基于一般比较原则:只有当两个实例都源于同一个类时,比较才具有意义。上述修改的代码也就是最好的了。
另外,还需要提示一点的是,在TestSon类中,equals方法还添加了super.equals(obj),添加该方法主要是对父类中重写的euqals也进行调用,因此当除了object类外,该类还有父类重写了euqals方法,则必须添加super.equals()。
此外,难道instanceof真一点用途都没有了吗?也不尽然,当所需比较类是final时,并且父类没有重写过equals方法时,则该类可以用instanceof进行比较判断。
分享到:
相关推荐
### Java中equals方法隐藏的陷阱 在Java编程中,正确实现`equals`方法至关重要,它不仅影响对象的比较逻辑,还直接关系到集合类(如`HashSet`、`HashMap`等)的行为。本文将深入探讨Java中`equals`方法的一些常见...
2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2....
在 Java 中,equals 方法是一个非常重要的方法,它用于判断两个对象是否相等,而不是判断两个对象的引用是否相同。在 Object 基类中,equals 方法的实现是使用“==”操作符来比较对象的引用,但是这并不满足实际需求...
在Java编程语言中,了解如何正确使用`==`和`equals()`方法是非常关键的,因为它们在比较对象和基本类型时有不同的行为。下面将详细解释这两个方法的工作原理、使用场景以及一些常见误区。 首先,`==`运算符主要用于...
Java 中 equals 和 == 的区别 Java 中的 equals 和 == 是两个不同的概念,很多开发者容易混淆它们。理解这两个概念的区别是非常重要的,因为它们对编程的正确性和性能都有很大的影响。 首先,我们需要了解 Java ...
java_equals用法,用来熟悉重写equals方法的
重载equals方法示例重载equals方法示例重载equals方法示例重载equals方法示例重载equals方法示例
#### 三、Students类中的equals方法实现分析 根据给定的代码片段,我们可以看到`Students`类中已经实现了`equals`方法。下面我们将详细分析这一实现。 ```java // Students类 public class Students { private ...
Java 中 equals 和 == 的区别 Java 中的 equals 和 == 是两个不同的运算符,它们之间的区别是非常重要的。 首先,我们需要了解 Java 中的内存模型。在 Java 中,变量可以分为两种:基本类型(primitive type)和...
Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.
equals 方法是 Object 类的方法,用于比较两个对象的值是否相等。对于基本数据类型,equals 方法不能用于比较,因为基本数据类型没有 equals 方法。 对于引用数据类型,equals 方法比较的是对象的值,而不是内存...
Java 中的 equals 方法是一种用于比较对象是否相等的方法,它是 Object 类中的一个方法。然而,重写 equals 方法并不是一件简单的事情,因为它需要遵守一些约定,否则可能会出现一些不可预期的行为。在这篇文章中,...
在Java编程语言中,`equals()`方法和`==`运算符是两个经常被用来比较对象是否相等的关键概念。理解它们的区别对于编写出正确、健壮的代码至关重要。 首先,`==`运算符用于基本类型(如int, char, boolean)的比较,...
Java中的`equals`方法是一个至关重要的方法,用于比较两个对象是否“相等”。在Java API规范中,`equals`方法必须遵循以下五个基本原则: 1. 对于任何引用类型,`o.equals(o)`总是返回`true`。 2. 如果`o.equals(o1...
默认情况下,equals 方法都是调用 Object 类的 equals 方法,而 Object 的 equals 方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象)。因此,如果我们想要比较两个对象的内容,我们需要重写 ...
首先,`equals()`方法是Java Object类中的一个方法,它的默认行为是基于对象的引用进行比较,即如果两个对象引用指向同一个内存地址,那么`equals()`返回`true`,否则返回`false`。然而,当我们在自定义类中重写`...
Java中equals()方法是Object类中定义的,作为所有类的父类,任何类都隐含地继承了该方法。 equals()方法用于判断两个对象的内容是否相同,如果没有重写该方法的类,需要重写该方法来实现对象内容的比较。 equals()...
// 输出 true,Integer类重写了equals方法来比较值而不是引用 ``` #### 字符串与`equals`方法 对于字符串,`equals`方法用于比较两个字符串的内容是否完全相同。这是因为`String`类重写了`Object`类中的`equals`...
除了String类以外,Java标准库中许多其他类也重写了equals方法,例如包装类Integer、Long等。对于包装类,equals方法不仅比较对象内容,还会考虑它们的数值大小。以下是一个使用Integer类的例子: ```java Integer ...
### set接口中hashCode和equals方法详解 #### 一、引言 在Java编程语言中,`Set`接口作为集合框架的重要组成部分,在实现无重复元素的数据结构方面扮演着关键角色。为了确保元素的唯一性,`Set`接口依赖于对象的`...