Object 提供的equals 方法: 类的每个实例都只与他的自身相等.指向同一个对象时才为true.
可以不覆盖equals方法的情况:
- 类的每个实例本质上都是唯一的.
- 不关心类是否提供了"逻辑相等"的测试功能
- 超类已经覆盖了equals, 从超类继承过来的行为对于子类也是合适的.
- 类是私有的或是包级私有的,可以确定它的equals方法永远不会被调用.
需要覆盖 equals 方法的情况:
类具有自己特有的"逻辑相等"概念,而不是对象等同,而且超类没有覆盖equals以实现期望的行为.
覆盖 equals 方法 通用约定:
equals 方法实现了等价关系:
- 自反性:对于任何非null 的引用值x, x.equals(x) = true
- 对称性:对于任何非null 的引用值x,y, 当且仅当 y.equals(x) = true 时, x.equals(y) = true 也成立.
- 传递性:对于任何非null 的引用值x,y,z, 如果 x.equals(y) = ture && y.equals(z) = true, 那么 x.equals(z) = true.
- 一致性:对于任何非null 的引用值x,y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用 x.equals(y) 就会一致的返回true, 或一致的返回 false.
- 对于任何非null的引用值x,x.equals(null) = false.
高质量的 equals 方法:
- 1 使用 == 操作符检查 "参数是否为这个对象的引用"
- 2 使用instanceof 操作符检查 "参数是否为正确的类型"
- 3 把参数转换为正确的类型
- 4 检查类中的每一个"关键"域:
- 4.1 基本类型域(除了float, double): 直接使用 ==
- 4.2 float 域: 使用 Float.compare
- 4.3 double 域: 使用 Double.compare
- 4.4 对象引用域: 递归调用 equals 方法, 并且需要注意 对象引用为 null时: (field == null ? o.field == null : field.equals(o.field)
- 5 编写完成后,检查是否是对称的,传递的,一致的?
最后的告诫:
- 覆盖 equals 方法时,总要覆盖hashCode
- 不要企图让equals方法过于智能
- 不要将equals 声明中的Object 对象替换为其他的类型. Object.equals参数是Object类型, 使用其他类型相当于是重载,而不是覆盖.
- @Override 注解的用法一致