一、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()方法呢?
- equals - 保证比较对象是否是绝对相等的
- hashCode - 保证在最快的时间内判断两个对象是否相等,可能有误差值
一个是保证可靠,一个是保证性能。也就是说:
同一个对象的hashCode一定相等,不同对象的hashCode也可能相等,这是因为hashCode是根据地址hash出来的一个int 32 位的整型数字,相等是在所难免,这里可以想象一下hash的链表图。
equals比较的是两个对象的地址,同一个对象地址肯定相同,不同的对象地址一定不同,可靠性是这么来的。
四、如果之重写了equals()方法,不重写hashcode()方法会有什么后果呢?
如果一个只重写了equals(比较所有属性是否相等)的类 new 出了两个属性相同的对象。这时可以得到的信息是这个属性相同的对象地址肯定不同,但是equals是true,hashCode返回的是不相等的(一般不会出现hash碰撞)。
也就是说这个类对象违背了Java对于两个对象相等的约定。违背约定的原因是 可靠的equals判断两个对象是相等的,但是他们两个的散列码却是不相等的。