重写hashCode和equals方法可以防止Java内存泄漏,在实际应用中可以有效的判断两个对象是否相等。

重写equals()方法

重写equals方法分为3个步骤

  1. 判断对象自身是否相等
  2. 使用 instanceof 运算符判断 对象 是否为自身类型的对象.
  3. 判断对象的数据域是否与自身的数据域相等

这里以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

 我们可以看到不重写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

 从结果中我们看出重写了hashcode方法的两个对象的hashcode值相等,没有重写的两个对象则不同。

那么在实际开发中,如果我们不重写hashCode()方法,我们new两个一样的对象

id=1,name="张三",address="湖北" 和

id=1,name="张三",address="湖北"

都用作key存入Map中,那么它就会存储两个不同的值,这样显然是不合理的。

所以在实际开发中,既要重写hashCode方法也要重写equals()方法.