关于hashcode和equals方法说明

一、前言

  我们都知道,要比较两个对象是否相等时需要调用对象的equals()方法,即判断对象引用所指向的对象地址是否相等,对象地址相等时,那么与对象相关的对象句柄、对象头、对象实例数据、对象类型数据等也是完全一致的,所以我们可以通过比较对象的地址来判断是否相等。

二、理解对象的存储

2.1Object源码理解

  对象在不重写的情况下使用的是Object的equals方法和hashcode方法,从Object类的源码我们知道,默认的equals 判断的是两个对象的引用指向的是不是同一个对象;而hashcode也是根据对象地址生成一个整数数值

  另外我们可以看到Object的hashcode()方法的修饰符为native,表明该方法是否操作系统实现,java调用操作系统底层代码获取哈希值。

public class Object {

public native int hashCode();

/**
* Indicates whether some other object is "equal to" this one.
* <p>
* The {@code equals} method implements an equivalence relation
* on non-null object references:
* <ul>
* <li>It is <i>reflexive</i>: for any non-null reference value
* {@code x}, {@code x.equals(x)} should return
* {@code true}.
* <li>It is <i>symmetric</i>: for any non-null reference values
* {@code x} and {@code y}, {@code x.equals(y)}
* should return {@code true} if and only if
* {@code y.equals(x)} returns {@code true}.
* <li>It is <i>transitive</i>: for any non-null reference values
* {@code x}, {@code y}, and {@code z}, if
* {@code x.equals(y)} returns {@code true} and
* {@code y.equals(z)} returns {@code true}, then
* {@code x.equals(z)} should return {@code true}.
* <li>It is <i>consistent</i>: for any non-null reference values
* {@code x} and {@code y}, multiple invocations of
* {@code x.equals(y)} consistently return {@code true}
* or consistently return {@code false}, provided no
* information used in {@code equals} comparisons on the
* objects is modified.
* <li>For any non-null reference value {@code x},
* {@code x.equals(null)} should return {@code false}.
* </ul>
* <p>
* The {@code equals} method for class {@code Object} implements
* the most discriminating possible equivalence relation on objects;
* that is, for any non-null reference values {@code x} and
* {@code y}, this method returns {@code true} if and only
* if {@code x} and {@code y} refer to the same object
* ({@code x == y} has the value {@code true}).
* <p>
* Note that it is generally necessary to override the {@code hashCode}
* method whenever this method is overridden, so as to maintain the
* general contract for the {@code hashCode} method, which states
* that equal objects must have equal hash codes.
*
* @param obj the reference object with which to compare.
* @return {@code true} if this object is the same as the obj
* argument; {@code false} otherwise.
* @see #hashCode()
* @see java.util.HashMap
*/
public boolean equals(Object obj) {
return (this == obj);
}
}

2.2 对象的存储方式

  Java是一种面向对象编程语言,它提供了类和对象的概念来组织和管理代码。在Java中,类是一种用户自定义的数据类型,它包含了属性和方法。对象是类的实例,可以通过调用对象的方法来操作对象的属性。在本文中,我们将深入探讨Java类与对象的存储方式。

  在Java中,每个对象都被存储在堆(heap)中。堆是一种运行时数据区,用于存储所有的对象,包括数组对象。当我们创建一个对象时,它会在堆中分配一段连续的内存空间,用于存储对象的属性值。

  例如,我们可以创建一个名为Person的类,该类包含了name和age两个属性:

package com.ruoyi.reserve.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.util.Objects;

/**
 * @author zs
 * @date 2019/12/24 15:42
 */
//@Data
//@AllArgsConstructor
//@NoArgsConstructor
//@EqualsAndHashCode(callSuper = false)
public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Person() {

    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /*@Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }*/

    /*@Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }*/
}

  现在,我们可以创建一个Person类的对象,并将其存储在堆中:

Person p = new Person("Alice", 25);

  在上面的代码中,我们创建了一个名为p的Person对象,并将其存储在堆中。p对象包含了name属性,其值为"Alice",以及age属性,其值为25。

2.3对象的生命周期

  在Java中,对象的生命周期由垃圾回收器(Garbage Collector)来管理。当一个对象不再被引用时,垃圾回收器会自动将其标记为垃圾对象,并在适当的时候释放它所占用的内存空间。这个过程称为垃圾回收。

  例如,如果我们将p引用设置为null,Person对象将不再被任何引用指向,并被垃圾回收器标记为垃圾对象:

p = null;

  在上面的代码中,我们将p引用设置为null,这意味着它不再指向任何对象。Person对象现在不再被任何引用指向,因此它将被标记为垃圾对象,并在适当的时候被垃圾回收器释放。

2.4对象的比较

2.4.1简单比较

  在Java中,我们可以使用==运算符来比较对象的引用是否相等。如果两个引用指向同一个对象,则它们相等。如果两个引用指向不同的对象,则它们不相等。

  例如,如果我们创建了两个Person对象,并将它们分别存储在p1和p2引用中,我们可以使用==运算符来比较它们是否相等:

Person p1 = new Person("Alice", 25);
Person p2 = new Person("Alice", 25);

if (p1 == p2) {
    System.out.println("p1 and p2 are the same object");
} else {
    System.out.println("p1 and p2 are different objects");
}

  在上面的代码中,我们创建了两个Person对象,并将它们分别存储在p1和p2引用中。由于p1和p2引用指向不同的对象,因此它们不相等,程序将输出"p1 and p2 are different objects"。

  如果我们想比较两个对象的属性值是否相等,我们需要使用equals方法。equals方法是Object类中定义的方法,用于比较两个对象是否相等。默认情况下,equals方法比较的是两个对象的引用,如果我们想比较属性值是否相等,我们需要在类中重写equals方法。

  例如,我们可以在Person类中重写equals方法,比较两个Person对象的name和age属性:

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Person person = (Person) obj;
    return age == person.age && Objects.equals(name, person.name);
}

  在上面的代码中,我们首先检查两个引用是否指向同一个对象,如果是,则它们相等。接下来,我们检查obj是否为null,以及它是否是Person类的实例,如果不是,则它们不相等。最后,我们比较两个对象的name和age属性是否相等,并返回比较结果。

  现在,我们可以使用equals方法来比较两个Person对象是否相等:

Person p1 = new Person("Alice", 25);
Person p2 = new Person("Alice", 25);

if (p1.equals(p2)) {
    System.out.println("p1 and p2 are equal");
} else {
    System.out.println("p1 and p2 are not equal");
}

  在上面的代码中,我们首先创建了两个Person对象,并将它们分别存储在p1和p2引用中。接下来,我们使用equals方法比较它们的属性值是否相等,由于它们的name和age属性值相等,因此它们相等,程序将输出"p1 and p2 are equal"。

总结

  在Java中,类和对象是组织和管理代码的重要概念。当我们创建一个对象时,它被存储在堆中,并由垃圾回收器来管理其生命周期。我们可以使用引用来访问和操作对象,并使用==运算符来比较对象的引用是否相等。如果我们想比较对象的属性值是否相等,我们需要在类中重写equals方法,并使用equals方法来比较两个对象的属性值是否相等。

2.4.2详细分析  

  我们再来详细看下输出结果:

  第一种情况:下面这个是没有重写equals、hashCode、toString的输出结果:

package com.ruoyi.reserve.controller;

import com.ruoyi.reserve.pojo.Person;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

/**
 * create by MrZs on 2020/8/20
 */
public class Test1 {

    public static void main(String[] args) {

        Person p1 = new Person("Alice", 25);
        Person p2 = new Person("Alice", 25);
        Person p3 = p1;
        //==比较的是对象的引用,对象的引用存储在栈中,对象的引用是对象在堆中的地址。
        System.out.println("p1:" + p1);//p1:com.ruoyi.reserve.pojo.Person@deb6432
        System.out.println("p2:" + p2);//p2:com.ruoyi.reserve.pojo.Person@28ba21f3
        System.out.println("p3:" + p3);//p3:com.ruoyi.reserve.pojo.Person@deb6432

        System.out.println("p1==p2:" + (p1 == p2));//p1==p2:false
        System.out.println("p1==p3:" + (p1 == p3));//p1==p3:true

        System.out.println("p1 equals p2:" + (p1.equals(p2)));//p1 equals p2:false
        System.out.println("p1 equals p3:" + (p1.equals(p3)));//p1 equals p3:true

        System.out.println("p1.hashCode:" + p1.hashCode());//p1.hashCode:233530418
        System.out.println("p2.hashCode:" + p2.hashCode());//p2.hashCode:683287027
        System.out.println("p3.hashCode:" + p3.hashCode());//p3.hashCode:233530418

        System.out.println("p1.System.identityHashCode:" + System.identityHashCode(p1));//p1.System.identityHashCode:233530418
        System.out.println("p2.System.identityHashCode:" + System.identityHashCode(p2));//p2.System.identityHashCode:683287027
        System.out.println("p3.System.identityHashCode:" + System.identityHashCode(p3));//p3.System.identityHashCode:233530418

    }
}

  第二种情况,下面这个是重写equals、hashCode、toString的输出结果:

public static void main(String[] args) {

        Person p1 = new Person("Alice", 25);
        Person p2 = new Person("Alice", 25);
        Person p3 = p1;
        //==比较的是对象的引用,对象的引用存储在栈中,对象的引用是对象在堆中的地址。
        System.out.println("p1:" + p1);//p1:Person{name='Alice', age=25}
        System.out.println("p2:" + p2);//p2:Person{name='Alice', age=25}
        System.out.println("p3:" + p3);//p3:Person{name='Alice', age=25}

        System.out.println("p1==p2:" + (p1 == p2));//p1==p2:false
        System.out.println("p1==p3:" + (p1 == p3));//p1==p3:true

        System.out.println("p1 equals p2:" + (p1.equals(p2)));//p1 equals p2:true
        System.out.println("p1 equals p3:" + (p1.equals(p3)));//p1 equals p3:true

        System.out.println("p1.hashCode:" + p1.hashCode());//p1.hashCode:1963862394
        System.out.println("p2.hashCode:" + p2.hashCode());//p2.hashCode:1963862394
        System.out.println("p3.hashCode:" + p3.hashCode());//p3.hashCode:1963862394

        System.out.println("p1.System.identityHashCode:" + System.identityHashCode(p1));//p1.System.identityHashCode:233530418
        System.out.println("p2.System.identityHashCode:" + System.identityHashCode(p2));//p2.System.identityHashCode:683287027
        System.out.println("p3.System.identityHashCode:" + System.identityHashCode(p3));//p3.System.identityHashCode:233530418
    Set set = new HashSet();
    set.add(p1);
    set.add(p2);
    System.out.println(set);

    Map m = new HashMap();
    m.put(p1, p1);
    m.put(p2, p2);

    System.out.println(m);
    System.out.println(System.identityHashCode(m.get(p1)));
    System.out.println(System.identityHashCode(m.get(p2)));


}

  分析下原因:

  关于hashcode:

  Java中获取对象的引用地址可以使用对象的hashCode()方法或者System.identityHashCode(Object obj)方法。

  方法一:使用对象的hashCode()方法

// 定义一个对象
Object obj = new Object();
// 获取对象的引用地址
int hashCode = obj.hashCode();
System.out.println("对象的引用地址为:" + hashCode);

  方法二:使用System.identityHashCode(Object obj)方法

// 定义一个对象
Object obj = new Object();
// 获取对象的引用地址
int hashCode = System.identityHashCode(obj);
System.out.println("对象的引用地址为:" + hashCode);

  注意:对象的hashCode()方法返回的是对象的哈希码,而System.identityHashCode(Object obj)方法返回的是对象的唯一标识,它不会被该对象的hashCode()方法重写所影响。

  关于toString:(https://blog.csdn.net/Li_Ya_Fei/article/details/130444097),不重写的话,调用的是Object的toString方法,打印的是下面这个鬼。

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

说明:String类型已经重写了hashcode和equals方法。

三、需要重写equals()的场景

  假设现在有很多学生对象,默认情况下,要判断多个学生对象是否相等,需要根据对象的引用地址判断,若对象的引用地址相等,那么对象的实例数据一定是一样的;

  但现在我们规定:当学生的姓名、年龄相等时,认为学生对象是相等的,不一定需要对象地址完全相同,这时候如果不重写Object的equals方法,那么返回的一定是false不相等,这个时候就

需要我们根据自己的需求重写equals()方法了。

  通过上面的例子,你是不是会想,不是说要同时重写Object的equals方法和hashcode方法吗?那上面的例子怎么才只用到equals方法呢,hashcode方法没有体现出来,不要着急,我们往下看。

四、需要重写hashcode()的场景

  以上面例子为基础,即p1和p2在重写equals方法后被认为是相等的。

  在两个对象equals的情况下进行把他们分别放入Map和Set中

  在上面的代码基础上追加如下代码:

Set set = new HashSet();
set.add(p1);
set.add(p2);
System.out.println(set);

  如果没有重写Object的hashcode()方法,这里会输出

[Person{name='Alice', age=25}, Person{name='Alice', age=25}]

说明该Set容器类有2个元素。.........等等,为什么会有2个元素????刚才经过测试,p1不是已经等于p2了吗,那按照Set容器的特性会有一个去重操作,那为什么现在会有2个元素。这就涉及到Set的底层实现问题了,这里简单介绍下就是HashSet的底层是通过HashMap实现的,最终比较set容器内元素是否相等是通过比较对象的hashcode来判断的。现在你可以试试把刚才注释掉的hashcode方法弄回去,然后重新运行,看是不是很神奇的就只输出一个元素了。

[Person{name='Alice', age=25}]

  同理,可以测试下放入HashMap中,Map也把两个同样的对象当成了不同的Key(Map的Key是不允许重复的,相同Key会覆盖),那么没有重写的情况下map中也会有2个元素,重写的情况下最后put进的元素会覆盖前面的value;

Map m = new HashMap();
m.put(p1, p1);
m.put(p2, p2);

System.out.println(m);
System.out.println(System.identityHashCode(m.get(p1)));
System.out.println(System.identityHashCode(m.get(p2)));

输出结果:

不重写hashcode:

"C:\Program Files\Java\jdk1.8.0_161\bin\java.exe" "-javaagent:D:\idea2022\IntelliJ IDEA 2022.2.2\lib\idea_rt.jar=59868:D:\idea2022\IntelliJ IDEA 2022.2.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;E:\project\nengy-backend\ruoyi-admin\target\classes;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-devtools\2.2.13.RELEASE\spring-boot-devtools-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot\2.2.13.RELEASE\spring-boot-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-context\5.2.12.RELEASE\spring-context-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-expression\5.2.12.RELEASE\spring-expression-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-autoconfigure\2.2.13.RELEASE\spring-boot-autoconfigure-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\io\springfox\springfox-boot-starter\3.0.0\springfox-boot-starter-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-oas\3.0.0\springfox-oas-3.0.0.jar;E:\config\maven\repository-zs\io\swagger\core\v3\swagger-annotations\2.1.2\swagger-annotations-2.1.2.jar;E:\config\maven\repository-zs\io\swagger\core\v3\swagger-models\2.1.2\swagger-models-2.1.2.jar;E:\config\maven\repository-zs\io\springfox\springfox-spi\3.0.0\springfox-spi-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-schema\3.0.0\springfox-schema-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-core\3.0.0\springfox-core-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-spring-web\3.0.0\springfox-spring-web-3.0.0.jar;E:\config\maven\repository-zs\io\github\classgraph\classgraph\4.8.83\classgraph-4.8.83.jar;E:\config\maven\repository-zs\io\springfox\springfox-spring-webmvc\3.0.0\springfox-spring-webmvc-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-spring-webflux\3.0.0\springfox-spring-webflux-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-swagger-common\3.0.0\springfox-swagger-common-3.0.0.jar;E:\config\maven\repository-zs\org\mapstruct\mapstruct\1.3.1.Final\mapstruct-1.3.1.Final.jar;E:\config\maven\repository-zs\io\springfox\springfox-data-rest\3.0.0\springfox-data-rest-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-bean-validators\3.0.0\springfox-bean-validators-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-swagger2\3.0.0\springfox-swagger2-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-swagger-ui\3.0.0\springfox-swagger-ui-3.0.0.jar;E:\config\maven\repository-zs\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;E:\config\maven\repository-zs\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;E:\config\maven\repository-zs\org\springframework\plugin\spring-plugin-core\2.0.0.RELEASE\spring-plugin-core-2.0.0.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-beans\5.2.12.RELEASE\spring-beans-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-aop\5.2.12.RELEASE\spring-aop-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\plugin\spring-plugin-metadata\2.0.0.RELEASE\spring-plugin-metadata-2.0.0.RELEASE.jar;E:\config\maven\repository-zs\io\swagger\swagger-models\1.6.2\swagger-models-1.6.2.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\core\jackson-annotations\2.10.5\jackson-annotations-2.10.5.jar;E:\config\maven\repository-zs\io\swagger\swagger-annotations\1.6.2\swagger-annotations-1.6.2.jar;E:\config\maven\repository-zs\mysql\mysql-connector-java\8.0.22\mysql-connector-java-8.0.22.jar;E:\project\nengy-backend\ruoyi-framework\target\classes;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-web\2.2.13.RELEASE\spring-boot-starter-web-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-json\2.2.13.RELEASE\spring-boot-starter-json-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.10.5\jackson-datatype-jdk8-2.10.5.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.10.5\jackson-datatype-jsr310-2.10.5.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\module\jackson-module-parameter-names\2.10.5\jackson-module-parameter-names-2.10.5.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-tomcat\2.2.13.RELEASE\spring-boot-starter-tomcat-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\apache\tomcat\embed\tomcat-embed-core\9.0.41\tomcat-embed-core-9.0.41.jar;E:\config\maven\repository-zs\org\apache\tomcat\embed\tomcat-embed-el\9.0.41\tomcat-embed-el-9.0.41.jar;E:\config\maven\repository-zs\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.41\tomcat-embed-websocket-9.0.41.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-validation\2.2.13.RELEASE\spring-boot-starter-validation-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\jakarta\validation\jakarta.validation-api\2.0.2\jakarta.validation-api-2.0.2.jar;E:\config\maven\repository-zs\org\hibernate\validator\hibernate-validator\6.0.22.Final\hibernate-validator-6.0.22.Final.jar;E:\config\maven\repository-zs\org\jboss\logging\jboss-logging\3.4.1.Final\jboss-logging-3.4.1.Final.jar;E:\config\maven\repository-zs\org\springframework\spring-web\5.2.12.RELEASE\spring-web-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-webmvc\5.2.12.RELEASE\spring-webmvc-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-aop\2.2.13.RELEASE\spring-boot-starter-aop-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\aspectj\aspectjweaver\1.9.6\aspectjweaver-1.9.6.jar;E:\config\maven\repository-zs\com\alibaba\druid-spring-boot-starter\1.2.6\druid-spring-boot-starter-1.2.6.jar;E:\config\maven\repository-zs\com\alibaba\druid\1.2.6\druid-1.2.6.jar;E:\config\maven\repository-zs\com\github\penggle\kaptcha\2.3.2\kaptcha-2.3.2.jar;E:\config\maven\repository-zs\com\jhlabs\filters\2.0.235-1\filters-2.0.235-1.jar;E:\config\maven\repository-zs\com\github\oshi\oshi-core\5.7.5\oshi-core-5.7.5.jar;E:\config\maven\repository-zs\net\java\dev\jna\jna\5.8.0\jna-5.8.0.jar;E:\config\maven\repository-zs\net\java\dev\jna\jna-platform\5.8.0\jna-platform-5.8.0.jar;E:\project\nengy-backend\ruoyi-system\target\classes;E:\project\nengy-backend\ruoyi-quartz\target\classes;E:\config\maven\repository-zs\org\quartz-scheduler\quartz\2.3.2\quartz-2.3.2.jar;E:\config\maven\repository-zs\com\mchange\mchange-commons-java\0.2.15\mchange-commons-java-0.2.15.jar;E:\project\nengy-backend\ruoyi-common\target\classes;E:\config\maven\repository-zs\org\springframework\spring-context-support\5.2.12.RELEASE\spring-context-support-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-security\2.2.13.RELEASE\spring-boot-starter-security-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\security\spring-security-config\5.2.8.RELEASE\spring-security-config-5.2.8.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\security\spring-security-core\5.2.8.RELEASE\spring-security-core-5.2.8.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\security\spring-security-web\5.2.8.RELEASE\spring-security-web-5.2.8.RELEASE.jar;E:\config\maven\repository-zs\com\github\pagehelper\pagehelper-spring-boot-starter\1.3.1\pagehelper-spring-boot-starter-1.3.1.jar;E:\config\maven\repository-zs\org\mybatis\spring\boot\mybatis-spring-boot-starter\2.1.4\mybatis-spring-boot-starter-2.1.4.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-jdbc\2.2.13.RELEASE\spring-boot-starter-jdbc-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\com\zaxxer\HikariCP\3.4.5\HikariCP-3.4.5.jar;E:\config\maven\repository-zs\org\springframework\spring-jdbc\5.2.12.RELEASE\spring-jdbc-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\mybatis\spring\boot\mybatis-spring-boot-autoconfigure\2.1.4\mybatis-spring-boot-autoconfigure-2.1.4.jar;E:\config\maven\repository-zs\org\mybatis\mybatis\3.5.6\mybatis-3.5.6.jar;E:\config\maven\repository-zs\org\mybatis\mybatis-spring\2.0.6\mybatis-spring-2.0.6.jar;E:\config\maven\repository-zs\com\github\pagehelper\pagehelper-spring-boot-autoconfigure\1.3.1\pagehelper-spring-boot-autoconfigure-1.3.1.jar;E:\config\maven\repository-zs\com\github\pagehelper\pagehelper\5.2.1\pagehelper-5.2.1.jar;E:\config\maven\repository-zs\com\github\jsqlparser\jsqlparser\4.0\jsqlparser-4.0.jar;E:\config\maven\repository-zs\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;E:\config\maven\repository-zs\org\apache\commons\commons-lang3\3.9\commons-lang3-3.9.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\core\jackson-databind\2.10.5.1\jackson-databind-2.10.5.1.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\core\jackson-core\2.10.5\jackson-core-2.10.5.jar;E:\config\maven\repository-zs\com\alibaba\fastjson\1.2.76\fastjson-1.2.76.jar;E:\config\maven\repository-zs\commons-io\commons-io\2.10.0\commons-io-2.10.0.jar;E:\config\maven\repository-zs\commons-fileupload\commons-fileupload\1.4\commons-fileupload-1.4.jar;E:\config\maven\repository-zs\org\apache\poi\poi-ooxml\4.1.2\poi-ooxml-4.1.2.jar;E:\config\maven\repository-zs\org\apache\poi\poi\4.1.2\poi-4.1.2.jar;E:\config\maven\repository-zs\commons-codec\commons-codec\1.13\commons-codec-1.13.jar;E:\config\maven\repository-zs\org\apache\commons\commons-collections4\4.4\commons-collections4-4.4.jar;E:\config\maven\repository-zs\org\apache\commons\commons-math3\3.6.1\commons-math3-3.6.1.jar;E:\config\maven\repository-zs\com\zaxxer\SparseBitSet\1.2\SparseBitSet-1.2.jar;E:\config\maven\repository-zs\org\apache\poi\poi-ooxml-schemas\4.1.2\poi-ooxml-schemas-4.1.2.jar;E:\config\maven\repository-zs\org\apache\commons\commons-compress\1.19\commons-compress-1.19.jar;E:\config\maven\repository-zs\com\github\virtuald\curvesapi\1.06\curvesapi-1.06.jar;E:\config\maven\repository-zs\org\yaml\snakeyaml\1.25\snakeyaml-1.25.jar;E:\config\maven\repository-zs\io\jsonwebtoken\jjwt\0.9.1\jjwt-0.9.1.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-data-redis\2.2.13.RELEASE\spring-boot-starter-data-redis-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\data\spring-data-redis\2.2.12.RELEASE\spring-data-redis-2.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\data\spring-data-keyvalue\2.2.12.RELEASE\spring-data-keyvalue-2.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\data\spring-data-commons\2.2.12.RELEASE\spring-data-commons-2.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-tx\5.2.12.RELEASE\spring-tx-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-oxm\5.2.12.RELEASE\spring-oxm-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\io\lettuce\lettuce-core\5.2.2.RELEASE\lettuce-core-5.2.2.RELEASE.jar;E:\config\maven\repository-zs\io\netty\netty-common\4.1.58.Final\netty-common-4.1.58.Final.jar;E:\config\maven\repository-zs\io\netty\netty-handler\4.1.58.Final\netty-handler-4.1.58.Final.jar;E:\config\maven\repository-zs\io\netty\netty-resolver\4.1.58.Final\netty-resolver-4.1.58.Final.jar;E:\config\maven\repository-zs\io\netty\netty-buffer\4.1.58.Final\netty-buffer-4.1.58.Final.jar;E:\config\maven\repository-zs\io\netty\netty-codec\4.1.58.Final\netty-codec-4.1.58.Final.jar;E:\config\maven\repository-zs\io\netty\netty-transport\4.1.58.Final\netty-transport-4.1.58.Final.jar;E:\config\maven\repository-zs\io\projectreactor\reactor-core\3.3.13.RELEASE\reactor-core-3.3.13.RELEASE.jar;E:\config\maven\repository-zs\org\reactivestreams\reactive-streams\1.0.3\reactive-streams-1.0.3.jar;E:\config\maven\repository-zs\org\apache\commons\commons-pool2\2.7.0\commons-pool2-2.7.0.jar;E:\config\maven\repository-zs\eu\bitwalker\UserAgentUtils\1.21\UserAgentUtils-1.21.jar;E:\config\maven\repository-zs\javax\servlet\javax.servlet-api\4.0.1\javax.servlet-api-4.0.1.jar;E:\config\maven\repository-zs\org\eweb4j\fel\0.8\fel-0.8.jar;E:\config\maven\repository-zs\org\antlr\antlr-runtime\3.4\antlr-runtime-3.4.jar;E:\config\maven\repository-zs\org\antlr\stringtemplate\3.2.1\stringtemplate-3.2.1.jar;E:\config\maven\repository-zs\antlr\antlr\2.7.7\antlr-2.7.7.jar;E:\config\maven\repository-zs\com\googlecode\aviator\aviator\3.3.0\aviator-3.3.0.jar;E:\config\maven\repository-zs\commons-beanutils\commons-beanutils\1.8.3\commons-beanutils-1.8.3.jar;E:\config\maven\repository-zs\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-freemarker\2.2.13.RELEASE\spring-boot-starter-freemarker-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\freemarker\freemarker\2.3.30\freemarker-2.3.30.jar;E:\project\nengy-backend\ruoyi-generator\target\classes;E:\config\maven\repository-zs\org\apache\velocity\velocity\1.7\velocity-1.7.jar;E:\config\maven\repository-zs\commons-lang\commons-lang\2.4\commons-lang-2.4.jar;E:\config\maven\repository-zs\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar;E:\config\maven\repository-zs\org\projectlombok\lombok\1.18.16\lombok-1.18.16.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-configuration-processor\2.2.13.RELEASE\spring-boot-configuration-processor-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\apache\xmlbeans\xmlbeans\3.1.0\xmlbeans-3.1.0.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-websocket\2.2.13.RELEASE\spring-boot-starter-websocket-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-messaging\5.2.12.RELEASE\spring-messaging-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-websocket\5.2.12.RELEASE\spring-websocket-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-test\2.2.13.RELEASE\spring-boot-starter-test-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter\2.2.13.RELEASE\spring-boot-starter-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-logging\2.2.13.RELEASE\spring-boot-starter-logging-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;E:\config\maven\repository-zs\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;E:\config\maven\repository-zs\org\apache\logging\log4j\log4j-to-slf4j\2.12.1\log4j-to-slf4j-2.12.1.jar;E:\config\maven\repository-zs\org\apache\logging\log4j\log4j-api\2.12.1\log4j-api-2.12.1.jar;E:\config\maven\repository-zs\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;E:\config\maven\repository-zs\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-test\2.2.13.RELEASE\spring-boot-test-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-test-autoconfigure\2.2.13.RELEASE\spring-boot-test-autoconfigure-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;E:\config\maven\repository-zs\net\minidev\json-smart\2.3\json-smart-2.3.jar;E:\config\maven\repository-zs\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;E:\config\maven\repository-zs\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;E:\config\maven\repository-zs\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;E:\config\maven\repository-zs\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;E:\config\maven\repository-zs\org\junit\jupiter\junit-jupiter\5.5.2\junit-jupiter-5.5.2.jar;E:\config\maven\repository-zs\org\junit\jupiter\junit-jupiter-api\5.5.2\junit-jupiter-api-5.5.2.jar;E:\config\maven\repository-zs\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;E:\config\maven\repository-zs\org\junit\platform\junit-platform-commons\1.5.2\junit-platform-commons-1.5.2.jar;E:\config\maven\repository-zs\org\junit\jupiter\junit-jupiter-params\5.5.2\junit-jupiter-params-5.5.2.jar;E:\config\maven\repository-zs\org\junit\jupiter\junit-jupiter-engine\5.5.2\junit-jupiter-engine-5.5.2.jar;E:\config\maven\repository-zs\org\junit\vintage\junit-vintage-engine\5.5.2\junit-vintage-engine-5.5.2.jar;E:\config\maven\repository-zs\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;E:\config\maven\repository-zs\org\junit\platform\junit-platform-engine\1.5.2\junit-platform-engine-1.5.2.jar;E:\config\maven\repository-zs\junit\junit\4.12\junit-4.12.jar;E:\config\maven\repository-zs\org\mockito\mockito-junit-jupiter\3.1.0\mockito-junit-jupiter-3.1.0.jar;E:\config\maven\repository-zs\org\assertj\assertj-core\3.13.2\assertj-core-3.13.2.jar;E:\config\maven\repository-zs\org\hamcrest\hamcrest\2.1\hamcrest-2.1.jar;E:\config\maven\repository-zs\org\mockito\mockito-core\3.1.0\mockito-core-3.1.0.jar;E:\config\maven\repository-zs\net\bytebuddy\byte-buddy\1.10.19\byte-buddy-1.10.19.jar;E:\config\maven\repository-zs\net\bytebuddy\byte-buddy-agent\1.10.19\byte-buddy-agent-1.10.19.jar;E:\config\maven\repository-zs\org\objenesis\objenesis\2.6\objenesis-2.6.jar;E:\config\maven\repository-zs\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;E:\config\maven\repository-zs\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;E:\config\maven\repository-zs\org\springframework\spring-core\5.2.12.RELEASE\spring-core-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-jcl\5.2.12.RELEASE\spring-jcl-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-test\5.2.12.RELEASE\spring-test-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\xmlunit\xmlunit-core\2.6.4\xmlunit-core-2.6.4.jar" com.ruoyi.reserve.controller.Test1

p1:com.ruoyi.reserve.study.basic.Person@deb6432
p2:com.ruoyi.reserve.study.basic.Person@28ba21f3
p3:com.ruoyi.reserve.study.basic.Person@deb6432
p1==p2:false
p1==p3:true
p1 equals p2:true
p1 equals p3:true
p1.hashCode:233530418
p2.hashCode:683287027
p3.hashCode:233530418
p1.System.identityHashCode:233530418
p2.System.identityHashCode:683287027
p3.System.identityHashCode:233530418
[com.ruoyi.reserve.study.basic.Person@deb6432, com.ruoyi.reserve.study.basic.Person@28ba21f3]
{com.ruoyi.reserve.study.basic.Person@deb6432=com.ruoyi.reserve.study.basic.Person@deb6432, com.ruoyi.reserve.study.basic.Person@28ba21f3=com.ruoyi.reserve.study.basic.Person@28ba21f3}
233530418
683287027


Process finished with exit code 0

 

重写hashcode:

"C:\Program Files\Java\jdk1.8.0_161\bin\java.exe" "-javaagent:D:\idea2022\IntelliJ IDEA 2022.2.2\lib\idea_rt.jar=59868:D:\idea2022\IntelliJ IDEA 2022.2.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;E:\project\nengy-backend\ruoyi-admin\target\classes;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-devtools\2.2.13.RELEASE\spring-boot-devtools-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot\2.2.13.RELEASE\spring-boot-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-context\5.2.12.RELEASE\spring-context-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-expression\5.2.12.RELEASE\spring-expression-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-autoconfigure\2.2.13.RELEASE\spring-boot-autoconfigure-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\io\springfox\springfox-boot-starter\3.0.0\springfox-boot-starter-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-oas\3.0.0\springfox-oas-3.0.0.jar;E:\config\maven\repository-zs\io\swagger\core\v3\swagger-annotations\2.1.2\swagger-annotations-2.1.2.jar;E:\config\maven\repository-zs\io\swagger\core\v3\swagger-models\2.1.2\swagger-models-2.1.2.jar;E:\config\maven\repository-zs\io\springfox\springfox-spi\3.0.0\springfox-spi-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-schema\3.0.0\springfox-schema-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-core\3.0.0\springfox-core-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-spring-web\3.0.0\springfox-spring-web-3.0.0.jar;E:\config\maven\repository-zs\io\github\classgraph\classgraph\4.8.83\classgraph-4.8.83.jar;E:\config\maven\repository-zs\io\springfox\springfox-spring-webmvc\3.0.0\springfox-spring-webmvc-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-spring-webflux\3.0.0\springfox-spring-webflux-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-swagger-common\3.0.0\springfox-swagger-common-3.0.0.jar;E:\config\maven\repository-zs\org\mapstruct\mapstruct\1.3.1.Final\mapstruct-1.3.1.Final.jar;E:\config\maven\repository-zs\io\springfox\springfox-data-rest\3.0.0\springfox-data-rest-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-bean-validators\3.0.0\springfox-bean-validators-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-swagger2\3.0.0\springfox-swagger2-3.0.0.jar;E:\config\maven\repository-zs\io\springfox\springfox-swagger-ui\3.0.0\springfox-swagger-ui-3.0.0.jar;E:\config\maven\repository-zs\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;E:\config\maven\repository-zs\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;E:\config\maven\repository-zs\org\springframework\plugin\spring-plugin-core\2.0.0.RELEASE\spring-plugin-core-2.0.0.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-beans\5.2.12.RELEASE\spring-beans-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-aop\5.2.12.RELEASE\spring-aop-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\plugin\spring-plugin-metadata\2.0.0.RELEASE\spring-plugin-metadata-2.0.0.RELEASE.jar;E:\config\maven\repository-zs\io\swagger\swagger-models\1.6.2\swagger-models-1.6.2.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\core\jackson-annotations\2.10.5\jackson-annotations-2.10.5.jar;E:\config\maven\repository-zs\io\swagger\swagger-annotations\1.6.2\swagger-annotations-1.6.2.jar;E:\config\maven\repository-zs\mysql\mysql-connector-java\8.0.22\mysql-connector-java-8.0.22.jar;E:\project\nengy-backend\ruoyi-framework\target\classes;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-web\2.2.13.RELEASE\spring-boot-starter-web-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-json\2.2.13.RELEASE\spring-boot-starter-json-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.10.5\jackson-datatype-jdk8-2.10.5.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.10.5\jackson-datatype-jsr310-2.10.5.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\module\jackson-module-parameter-names\2.10.5\jackson-module-parameter-names-2.10.5.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-tomcat\2.2.13.RELEASE\spring-boot-starter-tomcat-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\apache\tomcat\embed\tomcat-embed-core\9.0.41\tomcat-embed-core-9.0.41.jar;E:\config\maven\repository-zs\org\apache\tomcat\embed\tomcat-embed-el\9.0.41\tomcat-embed-el-9.0.41.jar;E:\config\maven\repository-zs\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.41\tomcat-embed-websocket-9.0.41.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-validation\2.2.13.RELEASE\spring-boot-starter-validation-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\jakarta\validation\jakarta.validation-api\2.0.2\jakarta.validation-api-2.0.2.jar;E:\config\maven\repository-zs\org\hibernate\validator\hibernate-validator\6.0.22.Final\hibernate-validator-6.0.22.Final.jar;E:\config\maven\repository-zs\org\jboss\logging\jboss-logging\3.4.1.Final\jboss-logging-3.4.1.Final.jar;E:\config\maven\repository-zs\org\springframework\spring-web\5.2.12.RELEASE\spring-web-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-webmvc\5.2.12.RELEASE\spring-webmvc-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-aop\2.2.13.RELEASE\spring-boot-starter-aop-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\aspectj\aspectjweaver\1.9.6\aspectjweaver-1.9.6.jar;E:\config\maven\repository-zs\com\alibaba\druid-spring-boot-starter\1.2.6\druid-spring-boot-starter-1.2.6.jar;E:\config\maven\repository-zs\com\alibaba\druid\1.2.6\druid-1.2.6.jar;E:\config\maven\repository-zs\com\github\penggle\kaptcha\2.3.2\kaptcha-2.3.2.jar;E:\config\maven\repository-zs\com\jhlabs\filters\2.0.235-1\filters-2.0.235-1.jar;E:\config\maven\repository-zs\com\github\oshi\oshi-core\5.7.5\oshi-core-5.7.5.jar;E:\config\maven\repository-zs\net\java\dev\jna\jna\5.8.0\jna-5.8.0.jar;E:\config\maven\repository-zs\net\java\dev\jna\jna-platform\5.8.0\jna-platform-5.8.0.jar;E:\project\nengy-backend\ruoyi-system\target\classes;E:\project\nengy-backend\ruoyi-quartz\target\classes;E:\config\maven\repository-zs\org\quartz-scheduler\quartz\2.3.2\quartz-2.3.2.jar;E:\config\maven\repository-zs\com\mchange\mchange-commons-java\0.2.15\mchange-commons-java-0.2.15.jar;E:\project\nengy-backend\ruoyi-common\target\classes;E:\config\maven\repository-zs\org\springframework\spring-context-support\5.2.12.RELEASE\spring-context-support-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-security\2.2.13.RELEASE\spring-boot-starter-security-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\security\spring-security-config\5.2.8.RELEASE\spring-security-config-5.2.8.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\security\spring-security-core\5.2.8.RELEASE\spring-security-core-5.2.8.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\security\spring-security-web\5.2.8.RELEASE\spring-security-web-5.2.8.RELEASE.jar;E:\config\maven\repository-zs\com\github\pagehelper\pagehelper-spring-boot-starter\1.3.1\pagehelper-spring-boot-starter-1.3.1.jar;E:\config\maven\repository-zs\org\mybatis\spring\boot\mybatis-spring-boot-starter\2.1.4\mybatis-spring-boot-starter-2.1.4.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-jdbc\2.2.13.RELEASE\spring-boot-starter-jdbc-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\com\zaxxer\HikariCP\3.4.5\HikariCP-3.4.5.jar;E:\config\maven\repository-zs\org\springframework\spring-jdbc\5.2.12.RELEASE\spring-jdbc-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\mybatis\spring\boot\mybatis-spring-boot-autoconfigure\2.1.4\mybatis-spring-boot-autoconfigure-2.1.4.jar;E:\config\maven\repository-zs\org\mybatis\mybatis\3.5.6\mybatis-3.5.6.jar;E:\config\maven\repository-zs\org\mybatis\mybatis-spring\2.0.6\mybatis-spring-2.0.6.jar;E:\config\maven\repository-zs\com\github\pagehelper\pagehelper-spring-boot-autoconfigure\1.3.1\pagehelper-spring-boot-autoconfigure-1.3.1.jar;E:\config\maven\repository-zs\com\github\pagehelper\pagehelper\5.2.1\pagehelper-5.2.1.jar;E:\config\maven\repository-zs\com\github\jsqlparser\jsqlparser\4.0\jsqlparser-4.0.jar;E:\config\maven\repository-zs\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;E:\config\maven\repository-zs\org\apache\commons\commons-lang3\3.9\commons-lang3-3.9.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\core\jackson-databind\2.10.5.1\jackson-databind-2.10.5.1.jar;E:\config\maven\repository-zs\com\fasterxml\jackson\core\jackson-core\2.10.5\jackson-core-2.10.5.jar;E:\config\maven\repository-zs\com\alibaba\fastjson\1.2.76\fastjson-1.2.76.jar;E:\config\maven\repository-zs\commons-io\commons-io\2.10.0\commons-io-2.10.0.jar;E:\config\maven\repository-zs\commons-fileupload\commons-fileupload\1.4\commons-fileupload-1.4.jar;E:\config\maven\repository-zs\org\apache\poi\poi-ooxml\4.1.2\poi-ooxml-4.1.2.jar;E:\config\maven\repository-zs\org\apache\poi\poi\4.1.2\poi-4.1.2.jar;E:\config\maven\repository-zs\commons-codec\commons-codec\1.13\commons-codec-1.13.jar;E:\config\maven\repository-zs\org\apache\commons\commons-collections4\4.4\commons-collections4-4.4.jar;E:\config\maven\repository-zs\org\apache\commons\commons-math3\3.6.1\commons-math3-3.6.1.jar;E:\config\maven\repository-zs\com\zaxxer\SparseBitSet\1.2\SparseBitSet-1.2.jar;E:\config\maven\repository-zs\org\apache\poi\poi-ooxml-schemas\4.1.2\poi-ooxml-schemas-4.1.2.jar;E:\config\maven\repository-zs\org\apache\commons\commons-compress\1.19\commons-compress-1.19.jar;E:\config\maven\repository-zs\com\github\virtuald\curvesapi\1.06\curvesapi-1.06.jar;E:\config\maven\repository-zs\org\yaml\snakeyaml\1.25\snakeyaml-1.25.jar;E:\config\maven\repository-zs\io\jsonwebtoken\jjwt\0.9.1\jjwt-0.9.1.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-data-redis\2.2.13.RELEASE\spring-boot-starter-data-redis-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\data\spring-data-redis\2.2.12.RELEASE\spring-data-redis-2.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\data\spring-data-keyvalue\2.2.12.RELEASE\spring-data-keyvalue-2.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\data\spring-data-commons\2.2.12.RELEASE\spring-data-commons-2.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-tx\5.2.12.RELEASE\spring-tx-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-oxm\5.2.12.RELEASE\spring-oxm-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\io\lettuce\lettuce-core\5.2.2.RELEASE\lettuce-core-5.2.2.RELEASE.jar;E:\config\maven\repository-zs\io\netty\netty-common\4.1.58.Final\netty-common-4.1.58.Final.jar;E:\config\maven\repository-zs\io\netty\netty-handler\4.1.58.Final\netty-handler-4.1.58.Final.jar;E:\config\maven\repository-zs\io\netty\netty-resolver\4.1.58.Final\netty-resolver-4.1.58.Final.jar;E:\config\maven\repository-zs\io\netty\netty-buffer\4.1.58.Final\netty-buffer-4.1.58.Final.jar;E:\config\maven\repository-zs\io\netty\netty-codec\4.1.58.Final\netty-codec-4.1.58.Final.jar;E:\config\maven\repository-zs\io\netty\netty-transport\4.1.58.Final\netty-transport-4.1.58.Final.jar;E:\config\maven\repository-zs\io\projectreactor\reactor-core\3.3.13.RELEASE\reactor-core-3.3.13.RELEASE.jar;E:\config\maven\repository-zs\org\reactivestreams\reactive-streams\1.0.3\reactive-streams-1.0.3.jar;E:\config\maven\repository-zs\org\apache\commons\commons-pool2\2.7.0\commons-pool2-2.7.0.jar;E:\config\maven\repository-zs\eu\bitwalker\UserAgentUtils\1.21\UserAgentUtils-1.21.jar;E:\config\maven\repository-zs\javax\servlet\javax.servlet-api\4.0.1\javax.servlet-api-4.0.1.jar;E:\config\maven\repository-zs\org\eweb4j\fel\0.8\fel-0.8.jar;E:\config\maven\repository-zs\org\antlr\antlr-runtime\3.4\antlr-runtime-3.4.jar;E:\config\maven\repository-zs\org\antlr\stringtemplate\3.2.1\stringtemplate-3.2.1.jar;E:\config\maven\repository-zs\antlr\antlr\2.7.7\antlr-2.7.7.jar;E:\config\maven\repository-zs\com\googlecode\aviator\aviator\3.3.0\aviator-3.3.0.jar;E:\config\maven\repository-zs\commons-beanutils\commons-beanutils\1.8.3\commons-beanutils-1.8.3.jar;E:\config\maven\repository-zs\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-freemarker\2.2.13.RELEASE\spring-boot-starter-freemarker-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\freemarker\freemarker\2.3.30\freemarker-2.3.30.jar;E:\project\nengy-backend\ruoyi-generator\target\classes;E:\config\maven\repository-zs\org\apache\velocity\velocity\1.7\velocity-1.7.jar;E:\config\maven\repository-zs\commons-lang\commons-lang\2.4\commons-lang-2.4.jar;E:\config\maven\repository-zs\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar;E:\config\maven\repository-zs\org\projectlombok\lombok\1.18.16\lombok-1.18.16.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-configuration-processor\2.2.13.RELEASE\spring-boot-configuration-processor-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\apache\xmlbeans\xmlbeans\3.1.0\xmlbeans-3.1.0.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-websocket\2.2.13.RELEASE\spring-boot-starter-websocket-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-messaging\5.2.12.RELEASE\spring-messaging-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-websocket\5.2.12.RELEASE\spring-websocket-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-test\2.2.13.RELEASE\spring-boot-starter-test-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter\2.2.13.RELEASE\spring-boot-starter-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-starter-logging\2.2.13.RELEASE\spring-boot-starter-logging-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;E:\config\maven\repository-zs\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;E:\config\maven\repository-zs\org\apache\logging\log4j\log4j-to-slf4j\2.12.1\log4j-to-slf4j-2.12.1.jar;E:\config\maven\repository-zs\org\apache\logging\log4j\log4j-api\2.12.1\log4j-api-2.12.1.jar;E:\config\maven\repository-zs\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;E:\config\maven\repository-zs\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-test\2.2.13.RELEASE\spring-boot-test-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\boot\spring-boot-test-autoconfigure\2.2.13.RELEASE\spring-boot-test-autoconfigure-2.2.13.RELEASE.jar;E:\config\maven\repository-zs\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;E:\config\maven\repository-zs\net\minidev\json-smart\2.3\json-smart-2.3.jar;E:\config\maven\repository-zs\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;E:\config\maven\repository-zs\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;E:\config\maven\repository-zs\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;E:\config\maven\repository-zs\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;E:\config\maven\repository-zs\org\junit\jupiter\junit-jupiter\5.5.2\junit-jupiter-5.5.2.jar;E:\config\maven\repository-zs\org\junit\jupiter\junit-jupiter-api\5.5.2\junit-jupiter-api-5.5.2.jar;E:\config\maven\repository-zs\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;E:\config\maven\repository-zs\org\junit\platform\junit-platform-commons\1.5.2\junit-platform-commons-1.5.2.jar;E:\config\maven\repository-zs\org\junit\jupiter\junit-jupiter-params\5.5.2\junit-jupiter-params-5.5.2.jar;E:\config\maven\repository-zs\org\junit\jupiter\junit-jupiter-engine\5.5.2\junit-jupiter-engine-5.5.2.jar;E:\config\maven\repository-zs\org\junit\vintage\junit-vintage-engine\5.5.2\junit-vintage-engine-5.5.2.jar;E:\config\maven\repository-zs\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;E:\config\maven\repository-zs\org\junit\platform\junit-platform-engine\1.5.2\junit-platform-engine-1.5.2.jar;E:\config\maven\repository-zs\junit\junit\4.12\junit-4.12.jar;E:\config\maven\repository-zs\org\mockito\mockito-junit-jupiter\3.1.0\mockito-junit-jupiter-3.1.0.jar;E:\config\maven\repository-zs\org\assertj\assertj-core\3.13.2\assertj-core-3.13.2.jar;E:\config\maven\repository-zs\org\hamcrest\hamcrest\2.1\hamcrest-2.1.jar;E:\config\maven\repository-zs\org\mockito\mockito-core\3.1.0\mockito-core-3.1.0.jar;E:\config\maven\repository-zs\net\bytebuddy\byte-buddy\1.10.19\byte-buddy-1.10.19.jar;E:\config\maven\repository-zs\net\bytebuddy\byte-buddy-agent\1.10.19\byte-buddy-agent-1.10.19.jar;E:\config\maven\repository-zs\org\objenesis\objenesis\2.6\objenesis-2.6.jar;E:\config\maven\repository-zs\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;E:\config\maven\repository-zs\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;E:\config\maven\repository-zs\org\springframework\spring-core\5.2.12.RELEASE\spring-core-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-jcl\5.2.12.RELEASE\spring-jcl-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\springframework\spring-test\5.2.12.RELEASE\spring-test-5.2.12.RELEASE.jar;E:\config\maven\repository-zs\org\xmlunit\xmlunit-core\2.6.4\xmlunit-core-2.6.4.jar" com.ruoyi.reserve.controller.Test1
p1:Person{name='Alice', age=25}
p2:Person{name='Alice', age=25}
p3:Person{name='Alice', age=25}
p1==p2:false
p1==p3:true
p1 equals p2:true
p1 equals p3:true
p1.hashCode:1963862394
p2.hashCode:1963862394
p3.hashCode:1963862394
p1.System.identityHashCode:233530418
p2.System.identityHashCode:683287027
p3.System.identityHashCode:233530418
[Person{name='Alice', age=25}]
{Person{name='Alice', age=25}=Person{name='Alice', age=25}}
683287027
683287027

Process finished with exit code 0

  可以看出来,这里是比较的是重写后的哈希值,而不是确定对象在内存中的唯一标识的哈希值。

五、原理分析

  因为我们没有重写父类(Object)的hashcode方法,Object的hashcode方法会根据两个对象的地址生成对相应的hashcode;p1和p2是分别new出来的,那么他们的地址肯定是不一样的,自然hashcode值也会不一样。

  • Set区别对象是不是唯一的标准是:两个对象hashcode是不是一样,再判定两个对象是否equals;
  • Map 是先根据Key值的hashcode分配,获取对象保存数组下标,然后再根据equals区分唯一值(详见下面的map分析)

六、补充HashMap知识

  • hashMap组成结构:hashMap是由数组和链表组成;
  • hashMap的存储:一个对象存储到hashMap中的位置是由其key的hashcode值决定的;
  • 查找key: 找key的时候,hashMap会先根据key的hashcode经过取余算法定位其所在数组的位置,再根据key的equals方法匹配相同key值获取对应的对象;

举例:

(1)hashmap存储

  • 存值规则:把Key的hashCode与HashMap的容量取余得出该Key存储在数组所在位置的下标(源码定位Key存储在数组的哪个位置是以hashCode & (HashMap容量-1)算法得出)这里为方便理解使用此方式;
//为了演示方便定义一个容量大小为3的hashMap(其默认为16)
HashMap map=newHashMap(3);

map.put("a",1); 得到key 为“a” 的hashcode 值为97,然后根据该值和hashMap容量取余97%3得到存储位到数组下标为1;

map.put("b",2); 得到key 为“b” 的hashcode 值为98,     98%3到存储位到数组下标为2;

map.put("c",3); 得到key 为“c” 的hashcode 值为99,   99%3到存储位到数组下标为0;

map.put("d",4); 得到key 为“d” 的hashcode 值为100,100%3到存储位到数组下标为1;

map.put("e",5); 得到key 为“e” 的hashcode 值为101,101%3到存储位到数组下标为2;

map.put("f",6); 得到key 为“f”  的hashcode 值为102,   102%3到存储位到数组下标为0;

 

(2)hashmap的查找key

  • 得到key在数组中的位置:根据上图,当我们获取key 为“a”的对象时,那么我们首先获得 key的hashcode97%3得到存储位到数组下标为1;
  • 匹配得到对应key值对象:得到数组下表为1的数据“a”和“c”对象, 然后再根据 key.equals()来匹配获取对应key的数据对象;
  • hashcode 对于HashMap:如果没有hashcode 就意味着HashMap存储的时候是没有规律可寻的,那么每当我们map.get()方法的时候,就要把map里面的对象一一拿出来进行equals匹配,这样效率是不是会超级慢;

(3)hashcode方法文档说明

  • 在equals方法没被修改的前提下,多次调用同一对象的hashcode方法返回的值必须是相同的整数;
  • 如果两个对象互相equals,那么这两个对象的hashcode值必须相等;
  • 为不同对象生成不同的hashcode可以提升哈希表的性能;
posted @ 2020-01-08 10:33  慎终若始  阅读(246)  评论(0编辑  收藏  举报