equals方法误用不同类型参数导致的问题
Posted Neo Yang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了equals方法误用不同类型参数导致的问题相关的知识,希望对你有一定的参考价值。
背景
最近重构代码引入了一个问题,原因是由于两个模块都定义常量 ONE。 一个定义是数字类型的1, 另一个模块定义的是“1”。其中一个模块使用了equals方法,将传入的字符串参数与常量ONE比较。
抽取了公共代码后,只保留了数字1的常量定义。由于要改的地方很多,import文件路径采用批量替换的方式处理,替换后代码编译没问题。系统上到生产环境后发现有问题了。
问题分析
Java对象都从Object中继承了equals()方法,用于判断两个对象是否相等。开发过程中可以重写equals方法,实现自己的相等比较逻辑。
由于Object的equals()方法入参是Object, 这就导致你可以将两个不同类型的对象做相等比较,编译器不会报错。但实际开发中,我们基本上不会将两个不同类型对象做相等比较。
编译器放过了这个错误,我们也浑然不觉,待系统部署后运行起来才发现问题。软件开发过程是问题发现得越晚,修复问题的成本越高。好的编程习惯是让编译器尽可能多的发现问题。
下面以一段代码为例说明equals方法容易出问题:
- 定义一个表示不同颜色的枚举。
/**
* 不同颜色枚举定义
*/
public enum EnumColor
RED("red"),
BLUE("blue");
private String color;
private EnumColor(String color)
this.color = color;
public String getColor()
return color;
- 业务逻辑代码根据传入不同的颜色参数做不同的事情
public static void handleColor(String color)
if (color.equals(EnumColor.RED))
// 处理红色
else if (color.equals(EnumColor.BLUE))
// 处理蓝色
这段代码编译没有任何问题,但执行结果不是我们想要的。代码中的equals方法传入的参数是EnumColor枚举,比较结果恒为false.
String的equals方法遇到类型不为String的入参,直接判定为false.
正确代码是如下:取出枚举对应的String变量值,再用于比较。
public static void handleColor(String color)
if (color.equals(EnumColor.RED.getColor()))
// 处理红色
else if (color.equals(EnumColor.BLUE.getColor()))
// 处理蓝色
写代码时一个不留神就出问题了。特别是在大批量重构代码时,合并了一些重复定义的常量,看起来差不多,编译器也没有报错。系统看起来也很正常,执行结果是错的。
如果可以在编译期就能发现这种疏忽,问题就不会留到现网,解决的成本也很低。
一种处理方案
- 定义一个相等比较工具类
package com.elon.common.utility;
/**
* 对象相等比较工具类. 该工具类解决不同类型的对象用equals比较编译不报错, 出问题不容易识别的问题.
*
* @author elon
* @since 1.0
*/
public class EqualCompare<T>
/**
* 字符串相等比较器. 常用的工具类可以定义为常量.
*/
public static final EqualCompare<String> STRING_EQUAL = new EqualCompare<>();
/**
* 对象相等比较.
*
* @param a 比较的对象
* @param b 比较的对象
* @return true-相等; false-不相等
*/
public boolean equals(T a, T b)
if (a == null)
return false;
return a.equals(b);
该类通过泛型变量设置了参与比较的参数类型,如果传递的参数类型不对,编译直接报错。说明一下,基本类型不需要用equals比较,基本类型相等比较使用==。
使用上面的工具类,如果参与比较的类型不是字符串。编译器飘红:
以上是关于equals方法误用不同类型参数导致的问题的主要内容,如果未能解决你的问题,请参考以下文章