问题1. new Student 对象两个.年龄和姓名都一样。问equase对象是否相等
答:不重写的话是不相等的,因为equase底层是==
public boolean equals(Object obj) {
return (this == obj);
}
示例:
Student student1=new Student();
student1.setCode("1111");
student1.setName("名字1");
//2080166188
System.out.println("student1的hashCode==="+student1.hashCode());
Student student2=new Student();
student2.setCode("1111");
student2.setName("名字1");
//1123225098
System.out.println("student2的hashCode==="+student2.hashCode());
boolean equals = student1.equals(student2);
//false
System.out.println("student1.equals(student2)=="+equals);
重写equase后 equals的值 是true:
问题二.只重写equase 不重写hashcode可以吗?
答:不可以。重写了equase 虽然相等的两个对象equase 的值会是true. 但是如果把对象存到HashMap,HashMap的key不能重复。不重写hashcode相等的对象会认为是不相等的:
为什么?
1. equals()相等的两个对象,hashCode()一定相等
而hashCode()相等的对象,equals()不一定相等。
hash类存储结构(HashSet、HashMap等等)添加元素会先重复性校验,校验的方式就是先判断hashCode是否相等,然后再判断equals方法,不相等就不会比对equals方法了。
不重写hashCode()默认使用的就是Object类的hashCode(),我们看下源码:
public native int hashCode();
是个native方法,其实hashcode是根据对象的内存地址经哈希算法得来的。
两个对象值相同,内存地址不同,只重写equals()而不重写hashcode()就会导致equals()相等的两个对象,hashcode()不同,hashcode的高效率就会变得无意义了。
Student类:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(code, student.code) && Objects.equals(name, student.name);
}
/* @Override
public int hashCode() {
return Objects.hash(code, name);
}*/
测试类:
public static void main(String[] args) {
Student student1=new Student();
student1.setCode("1111");
student1.setName("名字1");
System.out.println("student1的hashCode==="+student1.hashCode());
Student student2=new Student();
student2.setCode("1111");
student2.setName("名字1");
System.out.println("student2的hashCode==="+student2.hashCode());
boolean equals = student1.equals(student2);
System.out.println("student1.equals(student2)=="+equals);
Student student3=new Student();
student3.setCode("333");
student3.setName("名字3");
System.out.println("student3的hashCode==="+student3.hashCode());
Map<Student,String> map= new HashMap<>();
map.put(student1,"student1");
map.put(student2,"student2");
map.put(student3,"student3");
System.out.println(map.toString());
}
输出的值:
student1的hashCode===2080166188
student2的hashCode===1123225098
student1.equals(student2)==true
student3的hashCode===606548741
{Student{code='1111', name='名字1'}=student1,
Student{code='333', name='名字3'}=student3,
Student{code='1111', name='名字1'}=student2}
重写equals和hashcode后输出的值:
student1的hashCode===68164616
student2的hashCode===68164616
student1.equals(student2)==true
student3的hashCode===22973655
{Student{code='1111', name='名字1'}=student2,
Student{code='333', name='名字3'}=student3}
问题三.什么时候重写equals
答:想要比较两个对象里的所有字段都相等就要重写equals和hashcode. 因为默认是比较引用地址相当于==
注意:
如果 实体类里加 Lombok的@Data注解 就默认是重写了equals和hashcode
因为@Data相当于@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode这5个注解的合集。
但是@Data默认不会调用父类的equals和hashCode方法,当本类的值相等就返回true,父类的值不会对比,如果需求是父类也要对比,那在子类上加注解@EqualsAndHashCode(callSuper = true),并重写父类的equals和hashCode方法即可