重写hashCode和equals方法可以防止Java内存泄漏,在实际应用中可以有效的判断两个对象是否相等。
重写equals()方法
重写equals方法分为3个步骤
- 判断对象与自身是否相等
- 使用 instanceof 运算符判断 对象 是否为自身类型的对象.
- 判断对象的数据域是否与自身的数据域相等
这里以Peron类作为例子,重写equals和不重写equals区别。
public class ObjEqualsExample{
public static void main(String[] args) {
Person person = new Person(1,"张三", "湖北");
Person person2 = new Person(1,"张三", "湖北");
//这里使用equals重写
System.out.println(person.equals(person2));
Person2 person2_1 = new Person2(1,"张三", "湖北");
Person2 person2_2 = new Person2(1,"张三", "湖北");
//这里不使用equals重写
System.out.println(person2_1.equals(person2_2));
}
}
class Person {
private Integer id;
private String name;
private String address;
public Person(Integer id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
@Override
public boolean equals(Object o) {
if(o == this)
return true;
if(!(o instanceof Person))
return false;
if (o instanceof Person) {
Person person = (Person)o;
return person.id.equals(id)
&& person.name.equals(name)
&& person.address.equals(address)
;
}
return false;
}
}
class Person2 {
private Integer id;
private String name;
private String address;
public Person2(Integer id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
}
输出true
false
false
我们可以看到不重写equals时,在Person2中当相同的数据域进行比较的时候返回的是false,这显然不符合我们的实际开发需求,而我们按照上面的步骤重写了Person之后equals的比较就相等了。所以当new两个相同数据域有进行比较的操作的时候需要重写equas方法。
重写hashCode()方法
还是对上面的例子进行改写重写hashCode()方法。
public class ObjHashCodeExample {
public static void main(String[] args) {
Person person = new Person(1,"张三", "湖北");
Person person2 = new Person(1,"张三", "湖北");
//这里使用hashcode重写
System.out.println(person.hashCode());
System.out.println(person2.hashCode());
Person2 person2_1 = new Person2(1,"张三", "湖北");
Person2 person2_2 = new Person2(1,"张三", "湖北");
//这里不使用hashcode重写
System.out.println(person2_1.hashCode());
System.out.println(person2_2.hashCode());
}
}
class Person {
private Integer id;
private String name;
private String address;
public Person(Integer id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
@Override
public int hashCode(){
final int prime = 31;
int result = 1;
//重写每一个变量的hashcode值
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((address == null) ? 0 : address.hashCode());
return result;
}
@Override
public boolean equals(Object o) {
if(o == this)
return true;
if(!(o instanceof Person))
return false;
if (o instanceof Person) {
Person person = (Person)o;
return person.id.equals(id)
&& person.name.equals(name)
&& person.address.equals(address)
;
}
return false;
}
}
class Person2 {
private Integer id;
private String name;
private String address;
public Person2(Integer id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
}
输出
24949208
24949208
1956725890
356573597
24949208
1956725890
356573597
从结果中我们看出重写了hashcode方法的两个对象的hashcode值相等,没有重写的两个对象则不同。
那么在实际开发中,如果我们不重写hashCode()方法,我们new两个一样的对象
id=1,name="张三",address="湖北" 和
id=1,name="张三",address="湖北"
都用作key存入Map中,那么它就会存储两个不同的值,这样显然是不合理的。
所以在实际开发中,既要重写hashCode方法也要重写equals()方法.