问题1. new Student 对象两个.年龄和姓名都一样。问equase对象是否相等
    答:不重写的话是不相等的,因为equase底层是==

    1. public boolean equals(Object obj) {
    2. return (this == obj);
    3. }

    示例:

    1. Student student1=new Student();
    2. student1.setCode("1111");
    3. student1.setName("名字1");
    4. //2080166188
    5. System.out.println("student1的hashCode==="+student1.hashCode());
    6. Student student2=new Student();
    7. student2.setCode("1111");
    8. student2.setName("名字1");
    9. //1123225098
    10. System.out.println("student2的hashCode==="+student2.hashCode());
    11. boolean equals = student1.equals(student2);
    12. //false
    13. System.out.println("student1.equals(student2)=="+equals);

    image.png
    重写equase后 equals的值 是true:
    image.png
    问题二.只重写equase 不重写hashcode可以吗?
    答:不可以。重写了equase 虽然相等的两个对象equase 的值会是true. 但是如果把对象存到HashMap,HashMap的key不能重复。不重写hashcode相等的对象会认为是不相等的:
    为什么?
    1. equals()相等的两个对象,hashCode()一定相等
    而hashCode()相等的对象,equals()不一定相等。
    hash类存储结构(HashSet、HashMap等等)添加元素会先重复性校验,校验的方式就是先判断hashCode是否相等,然后再判断equals方法,不相等就不会比对equals方法了。
    不重写hashCode()默认使用的就是Object类的hashCode(),我们看下源码:

    1. public native int hashCode();

    是个native方法,其实hashcode是根据对象的内存地址经哈希算法得来的。
    两个对象值相同,内存地址不同,只重写equals()而不重写hashcode()就会导致equals()相等的两个对象,hashcode()不同,hashcode的高效率就会变得无意义了。

    1. Student类:
    2. @Override
    3. public boolean equals(Object o) {
    4. if (this == o) return true;
    5. if (o == null || getClass() != o.getClass()) return false;
    6. Student student = (Student) o;
    7. return Objects.equals(code, student.code) && Objects.equals(name, student.name);
    8. }
    9. /* @Override
    10. public int hashCode() {
    11. return Objects.hash(code, name);
    12. }*/

    测试类:

    1. public static void main(String[] args) {
    2. Student student1=new Student();
    3. student1.setCode("1111");
    4. student1.setName("名字1");
    5. System.out.println("student1的hashCode==="+student1.hashCode());
    6. Student student2=new Student();
    7. student2.setCode("1111");
    8. student2.setName("名字1");
    9. System.out.println("student2的hashCode==="+student2.hashCode());
    10. boolean equals = student1.equals(student2);
    11. System.out.println("student1.equals(student2)=="+equals);
    12. Student student3=new Student();
    13. student3.setCode("333");
    14. student3.setName("名字3");
    15. System.out.println("student3的hashCode==="+student3.hashCode());
    16. Map<Student,String> map= new HashMap<>();
    17. map.put(student1,"student1");
    18. map.put(student2,"student2");
    19. map.put(student3,"student3");
    20. System.out.println(map.toString());
    21. }

    输出的值:

    1. student1hashCode===2080166188
    2. student2hashCode===1123225098
    3. student1.equals(student2)==true
    4. student3hashCode===606548741
    5. {Student{code='1111', name='名字1'}=student1,
    6. Student{code='333', name='名字3'}=student3,
    7. Student{code='1111', name='名字1'}=student2}

    重写equals和hashcode后输出的值:

    1. student1hashCode===68164616
    2. student2hashCode===68164616
    3. student1.equals(student2)==true
    4. student3hashCode===22973655
    5. {Student{code='1111', name='名字1'}=student2,
    6. 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方法即可