javabean中重写hashcode()和equals()方法

本文探讨了在JavaBean中重写hashcode()和equals()方法的重要性,通过示例代码展示了如何进行重写,以确保对象比较的一致性和哈希表操作的正确性。

为什么要重写hashcode()和equals()方法

	在这之前先看一段代码

Person.java

public class Person {
		private int id;
		private String name;
		private double salary;
		private long account;
	
		public Person(int id, String name, double salary, long account) {
			super();
			this.id = id;
			this.name = name;
			this.salary = salary;
			this.account = account;
		}
		public int getId() {
			return id;
		}
		public void setId(int id) {
			this.id = id;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public double getSalary() {
			return salary;
		}
		public void setSalary(double salary) {
			this.salary = salary;
		}
		public long getAccount() {
			return account;
		}
		public void setAccount(long account) {
			this.account = account;
		}
}

Test.java


	public class Test {
	public static void main(String[] args) {
		Person person=new Person(1, "jim", 1000, 1000000);
		
		Person jim=new Person(1, "jim", 1000, 1000000);
		
		if(person.equals(jim)) {
			System.out.println("true");
		}else {
		System.out.println("false");
		}
	}
}
	最终程序运行的结果为false,这是为什么呢,其实也很好理解,因为在java中,每new一个对象就会给他分配到堆区,一般在栈区存储一个引用变量
指向这个堆区的内存空间,main方法中new了两个Person对象,那么这两个对象的在堆区的内存空间是不一样的,即使这两个对象的所有属性都相同,编译
器也不认为这两个对象其实是同一个对象,这有违现实生活的常理,如果两个人的身份证号,姓名完全相同,我们就认为他们是同一个人,事实上只需要身份
证相同就够了,那么如何做到让java语言也能实现这样的功能呢,这个时候需要我们重写equals()方法,那么怎么重写呢?

	前者对象叫person,后者叫jim
	1.首先,如果这个对象就是和它比较的对象分配在同一块堆区,那么这两个对象相等,
	2.如果这个比较的对象不为空,那么利用反射机制获取这个对象的类是不是和被比较的对象一致
	3.如果不一致,则无法比较,说明两个对象不相等
	4.如果一致,则要比较这两个对象的所有属性是否完全一致,一旦有一个不一致,则两对象不相等
	5,只有满足上面所有的条件后才能说明两个对象相等。
	具体方法就是在javabean中重写java.lang.Object下的equals方法。
	也就是在Person.java中重写equals()方法,添加代码如下
@Override
public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (account != other.account)
			return false;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
			return false;
		return true;
	}
	
	这个时候发现打印的结果为true,说明两个对象相等了,但是,还是有一个问题存在,我们重写的equals()方法仅仅只是让equals()方法认为两个
对象相等,事实上真的相等吗,其实不相等,因为堆区实际上还是存在两个对象person和jim,他们的内存空间仍然不同,这就和java语言的原理不一
致了,因为分配到堆区的内存空间实际上是hashcode()方法决定的,如果两个对象相等但hashcode却不同,也会给人一种误会,所以重写hashcode()
实际上是让编译器也认为两个对象相等,而不是我们一厢情愿的认为,事实上你可以通过重写equals()来达到不相等的两个对象返回值为true,上面就是一
个实际的例子,那么来看一下重写hashcode()的代码。
@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + (int) (account ^ (account >>> 32));
			result = prime * result + id;
			result = prime * result + ((name == null) ? 0 : name.hashCode());
			long temp;
			temp = Double.doubleToLongBits(salary);
			result = prime * result + (int) (temp ^ (temp >>> 32));
			return result;
		}
	简单介绍一下hashcode()的原理
	把某个非零常数值,例如17或者31(有兴趣可以百度一下为什么是这两个整数),保存在int型变量result中。
	对于对象中每一个关键域f(指equals方法中考虑的每一个域)参照以下原则处理。
	
	boolean型,计算(f ? 0:1)。
	byte、char和short型,计算(int)。
	long 型,计算(int)(f^(f>>>32))。
	float 型,计算Float.floatToIntBits(afloat)。
	double型,计算Double.doubleToLongBits(adouble)得到一个long,再执行long型的处理。
	对象引用,递归调用它的hashCode()方法。
	数组域,对其中每个元素调用它的hashCode()方法。

	 将上面计算得到的散列码保存到int型变量c,然后执行result=37×result+c。
	 返回result。

怎么重写hashcode()和equals()方法

	事实上重写hashcode()和equals()方法是非常简单的,基本编译器都会自带生成hashcode()和equals()方法只需要鼠标轻轻一点就可以了,eclipse
中是在source中,或者alt+shift+s,一般建议重写equals()方法时顺便重写hashcode(),如果是编译器自动生成则两个都被重写,在Set中时,因为Set
不能存储重复的元素,所以就涉及到了判断对象是否相等,如果只重写equals()方法而不重写hashcode()方法,那么根据hashcode值确定对象是否相等
的Set就会存储两个hashcode不同的但实际上相等的两个对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值