java equals与hashCode 两个重要方法的重写

比较两个String 的类内容是否相同时,使用了equals方法。其实,equals方法都是来自Object类,String 类对其进行了重写以满足字符串内容的要求。Object 类中设计这个方法就是为了让继承其的类来重写,以满足比较不同类型对象是否等价的要求。
在Object类中,改方法的实现相当于如下代码:

public boolean equals(Object obj){
      		 return (this==obj);
	}
从代码中可以看出,Object类的实现并没有比较两个对象是否等价的功能,而只是对两个应用进行了“==”比较,相当于比较两个引用是否指向同一个对象。因此,想真正具有比较对象是否等价的功能,需要在特定的类中根据比较规则重写此方法。
StringBuffer的equals方法不能比较内容是否相同,就是因为StringBuffer类没有重写equals方法。
使用哈希时被存储的对象需要提供一个哈希码(hash code),一般是一个整数值。hashCode()方法的功能就是用来提供所在对象的哈希码。根据对象的不同哈希码的值有所不同。一般定义一个新的类,就要为其重写一个合适的hashcode方法。
重写equals方法需要满足以下规定:
1.自反性:对于任何应用,只要不为null,那么其对自身使用equals方法将永远返回True,(x.equals(x)返回true);
2.对称性:对于任何引用a 与b,若都不为null,那么a对b,进行 equals 检查后得到的结果,与b对a进行equals检查得到的结果相同,也就是说a.equals(b)=b.equals(a).
3.传递性:对于任何非空引用值a,b,c,如果a对b进行equals检查返回True,并且b,对c 进行equals检查也返回True,那么a对c进行equals检查也返回True.
4.一致性:对于任何非空引用值a 和 b,在对象上参与equals比较的成员没有被修改的情况下,多次用a对b进行equals检查的结果应当始终相同。
5.null: 对任何非空引用值a,用其对null进行equals检查应当始终返回False.
(1) 首先应该测试两个引用是否指向同一个对象,如果是则直接返回True。这一步不是必须的,但可以提供比较时的性能。因为如果两个引用指向同一个对象,其equals测试返回True,不用再取比较任何内容。
(2)接下来应该测试传递进来的引用是否为null,如果是则直接返回False
(3)然后测试传递进来的对象引用是否通过自己类型的instanceof测试,如果不通过则返回False。因为传递进来的引用类型一点是Object类型,也就是说指向的对象可能是其他类型的,如果是其他类型的就没有可比性了。
(4)将传递进来的引用强制类型转换为自己的类型,测试相关的成员是否等价,成立则返回True,否则返回False.
以上重写equals方法时的基本步骤,但在实际操作中,还需要,特别注意一下两点:
(1)重写equals方法时访问限制必须为public类型,因为Object类中的钙方法已经是public类型,重写方法的访问限制只能与原来相同或者比原来宽。
(2)方法的入口参数必须为Object类型,不可以是别的类型
public boolean equals(Object o){
		 if(this==o){
			 return true;
		 }
		 if(o==null){
			 return false;
		 }
		 if(!(o instanceof Student)){
			 return false;
		 }
		 Student s=(Student)o;
		 if(this.name==s.name){
			 return true;
		 }else{
			 return false;
		 }
	 }

重写了equals方法就必须重写hashCode方法,否则两个等价的对象可能得到不同的哈希码,这在集合框架的使用中有可能产生严重的问题。
重写hashCode方法需要满足下列规定:
1.Java应用程序执行期间,于同一个对象上多次调用hashCode方法时,在对象上参与equals比较的成员没有被修改的情况下,必须一致地返回相同的整数。
2.从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保存一致。
3.如果两个对象各自调用hashcode方法产生不同的结果,对这两个对象进行equals比较一定返回False.
4.如果根据equals方法的比较,两个对象是等价的,那么两个对象中各级调用hashcode方法必须产生系统的整数结果
5.如果根据equals方法的比较,两个对象不等价,那么在两个对象中各自调用的hashcode方法不一定生成不同整数结果。
package com.org;


import java.util.Comparator;
import java.util.TreeSet;


public class Student implements Comparable{
	private int classNum;
	private String name;
	private int age;
	public Student(String name,int age, int classNum){
		this.name=name;
		this.classNum=classNum;
		this.age=age;
	}
	public String toString(){
		return "\n[name="+this.name+",age="+this.age+",classNum="+this.classNum+"]\n";
	}
	public boolean equals(Object o){
		 if(this==o){
			 return true;
		 }
		 if(o==null){
			 return false;
		 }
		 if(!(o instanceof Student)){
			 return false;
		 }
		 Student s=(Student)o;
		 if(this.name==s.name&&this.name.equals(s.name)&&this.classNum==s.classNum){
			 return true;
		 }else{
			 return false;
		 }
	 }
	public int hashCode(){
		return 7*this.name.hashCode()+13*Integer.valueOf(this.age).hashCode()+17*Integer.valueOf(this.classNum).hashCode();
	}
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		Student s=(Student)o;
		return this.classNum-s.classNum;
	}
	public static void main(String[] args){
		TreeSet ts1=new TreeSet(
				new Comparator(){
					public int compare(Object o1,Object o2){
						Student s1=(Student)o1;
						Student s2=(Student)o2;
						return s2.age-s1.age;
					}
				}
		);
		ts1.add(new Student("tom",21,97005));
		ts1.add(new Student("jerry",19,97003));
		ts1.add(new Student("lucy",18,97004));
		ts1.add(new Student("smith",28,97001));
		ts1.add(new Student("jc",23,97002));
		System.out.println(ts1);
		
		
		Student s1=new Student("jc",21,97001);
		Student s2=new Student("jc",21,97001);
		if(s1.equals(s2)){
			System.out.println("s1.hashCode()="+s1.hashCode());
			System.out.println("s2.hashCode()="+s2.hashCode());
		}else{
			System.out.println("两个对象不等价");
		}
	}
	
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值