过年结束了,今天想温故下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进行比较判断。
分享到:
相关推荐
2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2.javaequals()方法.zip2....
Java中equals方法隐藏的陷阱
能够加强对java中equals与==区别的理解。
java_equals用法,用来熟悉重写equals方法的
Java中的==与equals()实例方法Java中测试两个变量是否相等的方法有两个,一个是用==运算符,另一个就是object类提供的equals()方法。2
java中equals和==的区别.doc java中equals和==的区别.doc
重载equals方法示例重载equals方法示例重载equals方法示例重载equals方法示例重载equals方法示例
本文讲述了什么时候重写equals方法和如何重写equals方法。
Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.
Java equals 方法与hashcode 方法的深入解析.rar
equals方法重写作业,Students类,有三个属性id ,name ,grade。还有一个测试类用于测试创建了三个对象前两各对象的数据完全一样,第三个对象的数据不同。使用equals方法比较。并输出结果。
java 资料 equals 与== 的区别
主要介绍了浅谈java 重写equals方法的种种“坑”,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
主要介绍了Java中equals()方法重写实现代码的相关资料,需要的朋友可以参考下
Java语言深入_equals
JAVA中equals和的区别.doc
java中equals和的比较.doc
本文介绍了Java语言不直接支持关联数组,可以使用任何对象作为一个索引的数组,但在根Object类中使用 hashCode()方法明确表示期望广泛使用HashMap。理想情况下基于散列的容器提供有效插入和有效检索;直接在对象模式...
本文档详细介绍了set接口为什么会用到hashCode和equals方法以及这两个方法的一些探讨 set不同的实现类用到的这两个方法也不同