JAVA重写equals方法

时间:2022-03-06 16:06:34
VA问题的引出:今天编写贪吃蛇程序的时候遇到这样一个问题

public class Coordinate {

 public int headX, headY;

 Coordinate(int headX, int headY) {
  this.headX = headX;
  this.headY = headY;
 }
  
 public boolean equals(Coordinate c) {

   if(this.headX == c.headX && this.headY == c.headY) {

      return true;
   } else {

      return false;

   }
}

说明:Coordinate 是一个坐标类,重写equals方法的原因是要比较蛇身是否到达了记录下来的蛇头的转弯点,于是自己重写了equals方法,但是发现没有效果,即使x,y的值一样,返回的也是false。

为了进一步熟悉equals方法,于是自己又先写了下面一个验证的程序:

public class TestEquals {
 public static void main(String[] args) {
  Dog d1 = new Dog(1);
  Dog d2 = new Dog(1);
  System.out.println(d1 == d2);

  System.out.println(d1.equals(d2));
 }
}

class Dog {
 int weight;
 
 Dog(int weight) {
  this.weight = weight;
 }

 

  public boolean equals(Dog d) {

    if(this.weight == d.weight) {

       return true;

    } else {

       return false;

    }

  }
}

当然结果是一样的,为了进一步验证,于是就进一步重写了hashCode()方法:

public int hashCode() {

   return 0;

}

因为有时候优先比较的是hashCode码。但是结果还是不行。我只好找回原来看过的马士兵老师的视频教程,才发现自己对这个重写很不熟悉,正确的写法应该是:

public class Coordinate {

 public int headX, headY;

 Coordinate(int headX, int headY) {
  this.headX = headX;
  this.headY = headY;
 }
 
 public int hashCode() {
  return 0;
 }
 
 public boolean equals(Object obj) {
  if(obj == null) {
   return false;
  } else {
   if(obj instanceof Coordinate) {
    Coordinate coo = (Coordinate)obj;
    if(this.headX == coo.headX && this.headY == coo.headY) {
     return true;
    } else {
     return false;
    }
   }
  }
  return false;
 }
}

因为其传递的是Object类型,因此首先必要的是判断他是否为空,然后再判断他是不是自己要的类型:

obj instanceof Coordinate;

如果是则还要首先将其强制转换成自己要的类型。

Coordinate coo = (Coordinate)obj;

接着再进行判断,这样一来程序就正确了。

。。。。。。

剩下就是那个hashCode方法的重写了,这里没有重写hashCode()方法也是行的,所以不太清楚到底什么时候要重写该方法。尚有待考究。。。。。。

下面是网上某个博客找到的资料:

equals方法是Object的重要方法。重写遵循一下原则:

1.自反性,对于任何引用,只要不为null,那么对其自身使用equals方法永远放回true;
2.对称性,对于任何引用a,b.如果都不为nul,则a.equals(b)≡b.equals(a);
3.传递性,对于任何非空引用a,b,c,如果a.equals(b)==true,b.equals(c)==true,则a.equals(c)==true;
4.一致性,对于任何非空引用a,b,在参与equals比较的成员没有被修改的情况下,多次对a和b进行equals比较,结果应该始终相同;
5,任何非空引用a,a.equals(null)≡false;
通过一上几条规定可以得出重写equals方法有有一下几个步骤需要完成:
1,应该首先测试两个引用是否指向同一个对象.是则返回true,这一步可以提高效率;
2,接下来测试传进来的对象是否为空,是则返回false;
3,测试传进来的对象是否通过自己的instanceof,不通过则返回false;
4,将传进来的对象强制转换成自己的类型,对相关成员进行比较.

特别注意:
1.方法修饰符必须是public,因为是重写的Object的方法.
2.参数类型必须是Object.
3.重写了equals必须重写hashcode方法.否则两个等价对象可能得到不同的hashcode,这在集合框架中使用可能产生严重后果.

重写hashcode方法:
1.java程序运行期间,于同一对象多次调用hashcode方法时,在对象上参与equals比较的成员没有被修改的情况下,必须返回一直的整数.
2.从某一程序的执行到同一程序的另外一次执行,该整数无需保持一致.
3.如果两个对象各自调用hashcode方法返回的值不一致,那么这两个对象进行equals一定返回false.
4.如果equals方法返回true,则hashcode方法必须返回相同的值.
5.如果equals返回false,则hashcode比一定返回不同值.
*hashcode主要是用来提高hash系统的查询效率.
a.equals(b)==true必须a.hashcode()==b.hashcode();
a.hashcode!=b.hashcode则a.equals(b)==false;