为什么重写equals()方法时一定要重写hashCode()方法?
1.只写equals()方法不写hashCode()方法
我们先写一个equals()方法来测试下没有重写hashCode()方法的结果是什么样?
package com.appinfodb.entity;
import java.util.Objects;
public class Mobilephone {
private String id;//手机编号
private String name;//手机名字
private Integer num;//手机数量
public Mobilephone(String name,Integer num){
this.name=name;
this.num=num;
};
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Mobilephone phone = (Mobilephone) o;
return name == phone.name &&
num == phone.num &&
Objects.equals(name, phone.name);
}
}
写一个测试类,代码如下
public class Test {
public static void main(String[] args) throws Exception {
Mobilephone phone1=new Mobilephone("vivoY72",3);
Mobilephone phone2=new Mobilephone("vivoY72",3);
System.out.println("是同一部手机吗?"+phone1.equals(phone2));
System.out.println(phone1.hashCode());
System.out.println(phone2.hashCode());
}
}
结果如下图
出现这种情况时,由于Object自带的hashCode()方法根据对象的内存地址经哈希算法得来的,所以 phone1!= phone2,所以两者的 hashCode 值不一定相等。
2.在写了equals()方法之后,再加上hashCode()方法,代码如下
package com.appinfodb.entity;
import java.util.Objects;
public class Mobilephone {
private String id;//手机编号
private String name;//手机名字
private Integer num;//手机数量
public Mobilephone(String name,Integer num){
this.name=name;
this.num=num;
};
//重写equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Mobilephone phone = (Mobilephone) o;
return name == phone.name &&
num == phone.num &&
Objects.equals(name, phone.name);
}
//重写hashCode方法
@Override
public int hashCode() {
int result =1;
result = 31* result + name.hashCode();
result = 31 * result + num.hashCode();
return result;
}
}
测试代码不用发生改变,结果如下
可以看到重写了hashCode()方法之后,产生的哈希码值一样,同时也告诉我们对象和对象地址之间的关联性。
如果用一句话来说明:两个对象用equlas()方法进行判断,那么它们的地址也一定相等。
除了,上面这个方法之外,还有一个方法,那就是利用lombok注解解决。
1.添加lombok依赖
<!--lombok-->
<lombok.version>1.18.16</lombok.version>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
2.加上 @Data和 @EqualsAndHashCode注解
@Data注解:
这个注解包含了@Getter 、@Setter、 @RequiredArgsConstructor 、@ToString 和@EqualsAndHashCode这5个注解。
@EqualsAndHashCode注解:
(1)此注解会生成 equals(Object other) 和 hashCode()方法。
(2)它默认使用非静态,非瞬态的属性。
(3)可通过参数exclude排除一些属性,起到了筛选作用。
(4)可通过参数of指定仅使用哪些属性。
(5)它默认仅使用该类中定义的属性且不调用父类的方法。
(6)可通过callSuper=true解决上一点问题。让其生成的方法中调用父类的方法。
@Data
@EqualsAndHashCode(exclude = {"name","price"})
注意:
@EqualsAndHashCode注解一般情况下是不需要写上去的,除非你自己需要排除或者指定一些属性的时候,写上这个注解。