equals是java中最基础的方法,用来比较对象内容,Object中默认的实现是==比较,通常我们在编写自己的类时都会涉及到重写该方法,所以对该方面有个全面深刻的理解和认知是非常有必要的;
首先我们要明白equals约定是为了比较对象内容的,对象的内容进一步理解就是对象的域;要想写出优秀的equals方法,必须明确Java语言规范对equals有哪些特性要求,大致有以下几点:
- 自反性:对于任何非空引用x,x.equals(x)都应返回true;
- 对称性:对于任何引用x和y,当且仅当y.equals(x)返回true,x.equals(y)也应该返回true;
- 传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true;
- 一致性:如果x和y引用的对象没有发生变化,反复调用x.equals(y)应该返回一样的结果;
- 对于任意非空引用x,x.equals(null)都应该返回false;
基于以上分析,我们可以总结出一些经验和建议,以指导我们编写出更加合理和完美的equals方法:
- 显式参数命名为otherObject,因为稍后会对其进行类型转换得到other变量;
- 检测this与otherObject是否引用同一对象;
- 检测otherObject是否为空;
- 比较this和otherObject是否属于同一个类,有两种方式:getClass和instanceof;如果equals的语义在每个子类中有所改变则使用getClass,如果所有子类都拥有统一的语义则使用instanceof;
- 将otherObject转换为this对应的类型,得到other;
- 现在开始对所有需要比较的域进行比较,使用==比较基本类型域,使用equals比较对象域;
遵循以上原则基本上就可以编写出准确统一的equals方法;
文献参考:
[1]: 《Core Java. Volume I. Fundamentals, 8th Edition》