购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

陷阱21

一字之差
——重写对象的hashCode方法,但重写equals方法时参数不是Object类型

在进行程序开发时重写了equals方法,但是没有重写hashCode方法,会导致程序在某些情况下出错,同样,如果重写了对象的hashCode方法,但是没有重写equals方法或重写equals方法时参数不是Object类型,程序在某些情况下也一样会出现错误。

注 意

Object类的equals方法其参数必须是Object类型的,如果其直接子类或间接子类重写该方法,一定要保证其参数也是Object类型,否则在进行一些特殊处理(如判断HashMap集合中是否包含某个对象)时,程序就会出现错误,再有就是在比较两个对象时,也一定要重写equals方法,否则程序一样会出错。

下面看一个重写对象的hashCode方法,但是没有重写equals方法,导致程序出错的实例。

例3.21.1 创建类,在该类中重写对象的hashCode方法,但不重写equals方法,然后创建该类的两个实例,将其中一个实例放到HashSet集合中,并判断该集合中是否包含另一个对象,最后再通过对象的equals方法比较两个对象是否相同。(光盘位置:光盘\MR\Instance\3\21\ RewriteHashCodeApp)

运行本实例,将在控制台输出如图3.21 所示的信息。

图3.21 重写hashCode方法而没重写equals方法

说 明

从图3.21 的输出结果可以看出,由于重写了对象的hashCode方法,所以前两行输出对象book1 和book2 的散列码相同,都是 71349994,第3行输出false,表示Set集合中不包含对象book2,这是由于在重写hashCode方法的同时,没有重写equals方法,所以导致这样的结果,最后一行也输出了false,说明两个对象book1 与book2 是不相同的,这也是由于在重写hashCode方法的同时没有重写equals方法所导致的。

下面再看一个重写对象的hashCode方法,同时也重写了equals方法,但是重写equals方法的参数不是Object类型导致程序出错的实例。

例3.21.2 创建类,在该类中重写对象的hashCode方法,同时也重写了equals方法,但是重写equals方法的参数不是Object类型而是Book类型,然后创建该类的两个实例,将其中一个实例放到HashSet集合中,并判断该集合中是否包含另一个对象,最后再通过这个equals方法比较两个对象是否相同。(光盘位置:光盘\MR\Instance\3\21\EqualsParameterErrorApp)

运行本实例,将在控制台输出如图3.22 所示的信息。

图3.22 重写equals方法,但参数不是Object类型

说 明

从图3.22 的输出结果可以看出,由于重写了对象的hashCode方法,所以前两行输出对象book1 和book2 的散列码相同,都是 71349994,第3行输出false,表示Set集合中不包含对象book2,这是由于在重写equals方法时,其参数不是Object类型,实际上该方法在这里是重载了对象的equals方法,而不是重写对象的equals方法,所以导致这样的错误结果,最后一行输出了true,说明两个对象book1 与book2 是相同的,这是由于该类重载的equals方法,其参数是Book类型,因此可以对Book类的实例进行比较。

下面再看一个重写对象的hashCode方法,同时也正确地重写了对象的equals方法,使用程序能够输出正确结果的实例。

例3.21.3 创建类,在该类中重写了对象的hashCode方法和equals方法,然后创建该类的两个实例,将其中一个实例放到HashSet集合中,并判断该集合中是否包含另一个对象,最后再通过equals方法比较两个对象是否相同。(光盘位置:光盘\MR\Instance\3\21\RightEqualsMethodApp)

运行本实例,将在控制台输出如图3.23 所示的信息。

说 明

本实例之所以输出了正确的结果,是由于程序正确地重写了对象的hashCode方法和equals方法,所以输出结果的最后两行都输出了true,这样达到了程序预期的要求。

图3.23 正确重写对象的方法输出的结果

编程准则:一定要同时重写对象的equals和hashCode方法

无论在什么情况下,如果需要重写对象的equals方法和hashCode方法,一定要同时重写这两个方法,不能只重写其中的一个方法,并且在重写对象的equals方法时,一定要注意该方法的形参类型必须要是Object类型的,而不能是其他类型。 hQtrnvb64bjiFlw8Sh5bPcVfR36aj9eMoC8p0U14bztSuMV8OlYmMjBX2M9lZQBV

点击中间区域
呼出菜单
上一章
目录
下一章
×