`
JackAndroid
  • 浏览: 134971 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java类的equals方法

阅读更多

  过年结束了,今天想温故下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方法)定义的很详细,必须满足以下方面:

 

  1. 自反性:x.euqals(x);
  2. 对称性:x.equals(y), y.equals(x);
  3. 传递性:x.euqals(y),y.equals(z),z.equals(x);
  4. 一致性:在一致状态下,x.equals(y)总是返回一致状态;
  5. 能与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进行比较判断。


 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics