运行时对象的识别以及重写hashcode()和equals()方法

一、Java中对象比较是否相等的两种方法

1、通过“==”进行比较,这种比较的是两个对象的引用地址是否相同,即两个引用地址是否指向了同一对象
2、通过equals()方法进行比较,但是在Object类的源码中我们可以看到:因此它实际上还是通过方法1进行比较的。但是我们可以重写equals()方法。

package java.lang;  
 
public class Object {  
 
    public boolean equals(Object obj) {  
        return (this == obj);  
    }  
} 

比如java.long.String的源码中String自身就重写了equals()方法。

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}
二、重写equals()方法,实现不同session查询相同对象的比较

(1)在Hibernate中,如果是在同一个session中根据相同查询所得到的相同记录,则它们会拥有相同的Java识别
栗子:这段代码返回值为true

Session session = sessions.openSession();
Person p1 = (Person)session.get(Person.class,1);
Person p2 =(Person)session.get(Person.class,1);
session.close();
System.out.println(p1 = = p2);

(2)若开启两个session去查询相同的对象,是不会被识别为同一对象的。
栗子:这段代码返回值为false

Session session1 = sessions.openSession();
Person p1 = (Person)session.get(Person.class,1);
session1.close();
Session session2 = sessions.openSession();
Person p2 = (Person)session.get(Person.class,1);
session2.close();
System.out.println(p1 == p2);

因此,若我们想要在不同的查询中判断对象的内容是否一致,我们需要重写equals()和hashcode()方法,如下:
重写过后上面(2)中代码返回值为true

public boolean equals(Object obj) {        
		//引用相同
		if(this == obj) return true;
		//没有引用
		if(obj == null) return false;
		//实例不正确
		if(!(obj instanceof User)) return false;
		
		User other = (User)obj;
		if(id != other.id) {
			return false;
		}
		if(age != other.age) {
			return false;
		}
		if(!name.equals(other.name)) {
			return false;
		}
		if(gender !=null && other.gender != null)
		{
			if(!gender.equals(other.gender)) {
			return false;
			}
		}
		if(!birthday.equals(other.birthday)){
			return false;
		}
		
		return true;
	}
public int hashCode() {        
		int result;        
		result = getName().hashCode();        
		result = 29 * result + getBirthday().hashCode();
		result = 29 * result + getAge();
		return result;    
	}
三、为什么重写equals()方法就必须重写hashcode()方法呢?
  1. equals - 保证比较对象是否是绝对相等的
  2. hashCode - 保证在最快的时间内判断两个对象是否相等,可能有误差值
    一个是保证可靠,一个是保证性能。也就是说:
    同一个对象的hashCode一定相等,不同对象的hashCode也可能相等,这是因为hashCode是根据地址hash出来的一个int 32 位的整型数字,相等是在所难免,这里可以想象一下hash的链表图。
    equals比较的是两个对象的地址,同一个对象地址肯定相同,不同的对象地址一定不同,可靠性是这么来的。
四、如果之重写了equals()方法,不重写hashcode()方法会有什么后果呢?

如果一个只重写了equals(比较所有属性是否相等)的类 new 出了两个属性相同的对象。这时可以得到的信息是这个属性相同的对象地址肯定不同,但是equals是true,hashCode返回的是不相等的(一般不会出现hash碰撞)。
也就是说这个类对象违背了Java对于两个对象相等的约定。违背约定的原因是 可靠的equals判断两个对象是相等的,但是他们两个的散列码却是不相等的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值