手记

说说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进行的,这是一个需要注意的点。


0人推荐
随时随地看视频
慕课网APP