Java工程师面试必问的equals属性知识

我们平常判断两个对象是否相等时直接使用.equals()方法,但你有思考过equals比较的是两个对象的值还是引用地址嘛?

这个问题基本上是面试的常客

提问

请判断,两个对象值相同(x.equals(y) == true),但却可有不同的hash code , 该说法是否正确,为什么?

结合提问,请跟着小雷一起敲一遍代码,下次面试遇到这个问题咱再也不怕了。

涉及到equals肯定少不了equals被重写的场景,下面我将分4个场景介绍。

首先,我们创建一个Student对象,name和age属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class Student {

private String name;
private int age;

public Student(String name, int age) {
this.name = name;
this.age = 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;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student)) return false;

Student student = (Student) o;

if (getAge() != student.getAge()) return false;
return getName().equals(student.getName());
}

@Override
public int hashCode() {
int result = getName().hashCode();
result = 31 * result + getAge();
return result;
}
}

基于Junit编写测试方法

1
2
3
4
5
6
7
8
9
10
11
@Test
public void testEquals()
{
Student x = new Student("cheng", 20);
Student y = new Student("cheng", 20);
System.out.println("x.equals(y) is " + x.equals(y));
System.out.println("x.hashCode = " + x.hashCode());
System.out.println("y.hashCode = " + y.hashCode());
System.out.println("x memory address : " + System.identityHashCode(x));
System.out.println("y memory address : " + System.identityHashCode(y));
}

1、equals()和hashCode()被重写

如上Student类中equals和hashCode被重写了,运行测试代码结果如下

1
2
3
4
5
x.equals(y) is true
x.hashCode = -1361517349
y.hashCode = -1361517349
x memory address : 1623822117
y memory address : 549696331

从结果中可以看到,equals和hashCode被重写, 比较结果为true, hashCode一样,内存地址不一样

2、equals被重写,hashCode没有被重写

在Student类中,将hashCode()方法注释掉,运行测试代码如下:

1
2
3
4
5
x.equals(y) is true
x.hashCode = 1823390262
y.hashCode = 145510702
x memory address : 1823390262
y memory address : 145510702

从结果中可以看到,equals被重写,hashCode没有被重写, 比较结果为true, hashCode不一样,内存地址不一样,且x的hashcode和x的内存地址数值一样,y的hashcode和y的内存地址数值一样

3、equals没被重写,hashCode也没被重写

在Student类中,将equals方法和hashCode方法注释掉,运行测试代码结果如下:

1
2
3
4
5
x.equals(y) is false
x.hashCode = 908299026
y.hashCode = 857240709
x memory address : 908299026
y memory address : 857240709

从结果中可以看到,equals没被重写,hashCode也没被重写, 比较结果为false,hashCode不一样,内存地址不一样,且x的hashcode和x的内存地址数值一样,y的hashcode和y的内存地址数值一样

4、equals没被重写,hashCode被重写

在Student类中,将equals方法注释掉,运行测试代码结果如下:

1
2
3
4
5
x.equals(y) is false
x.hashCode = -1361517349
y.hashCode = -1361517349
x memory address : 1887922615
y memory address : 854077600

从结果中可以看到,equals没被重写,hashCode被重写, 比较结果为false, hashCode一样,内存地址不一样

总结:

提问:
请判断,两个对象值相同(x.equals(y) == true),但却可有不同的hash code , 该说法是否正确,为什么?

答: 该说法正确,当重写了equals方法但没重写hashCode方法,就会出现这样的问题。

注释:建议将equals和hashCode两个方法一起重写

如果你喜欢本文,请长按二维码关注