说说JAVA当中的equals

2018/11/29

说说JAVA当中的equals

equals这个属于Object类的方法,几乎每天都在用,可是看着它,却是既熟悉,又陌生。

先来看看Object中的equals中写了什么:

public boolean equals(Object obj) {
return (this == obj);
}

恩...似乎没有什么用,只是把当前对象的引用与传入的obj进行对比,于是,就会出现这么样的一个情况:

String s1 = new String("1");
String s2 =new String("1");

System.err.println(s1 == s2);

结果为false,就是因为s1与s2是不同的两个对象。

好,那么接下来来看看String是怎么重写equals方法的:

public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}

代码一大堆,但还是很好理解的,首先判断引用是否相同,其次判断是否属于String类,最后再判断字符序列。

所以,当需要比较两个对象的时候,需要重写equals方法。

那么重写equals时,一定得重写hashCode方法?

那么hashCode又是什么?能吃吗?

hash,翻译过来又称哈希、散列,那么学过数据结构的都知道hash table是什么东西。

这里不深入讨论,回到equals,如果重写equals的同时不重写hashCode的时候,你的代码可能会出现一些莫名其妙的BUG。

来看一个例子:

假设有这么样的一个类:

class Person{
private String name;


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

@Override
public boolean equals(Object obj) {
if(obj instanceof Person){
Person person = (Person)obj;
if(person.getName().equals(this.getName())){
return true;
}
}
return false;
}

public String getName() {
return name;
}
}

这个Person类重写了equals方法,使用判断名字来判断两个对象是否相等。

我们使用一个哈希表来储存Person与年龄的映射关系:

Map<Person,Integer> map = new HashMap<>();

向map当中放入两个人:

map.put(new Person("小明"),25);

map.put(new Person("小红"),18);

下面一段代码的预期值为25:

System.out.println(map.get(new Person("小明")));

但是结果却为null,为什么?

原因就是在HashMap当中判断两个对象相等,是通过hashCode进行的,这是一个需要注意的点。

Post Directory