跳转至

对于所有对象都通用的方法

  • 所有对象都通用的方法:
    • equals
    • hashCode
    • toString
    • clone
    • finalize

覆盖equals时请遵守通用约定

  • 期望的结果:
    • 类的每一个实例本质上都是唯一的
    • 这些类没有必要提供“逻辑相等”的测试功能
    • 超类已经覆盖了equals,超类的行为对于这个类也是合适的
    • 类是私有的,或者是包级私有的,可以确定其equals方法永远不会被调用
  • 需要重写equals的时候:类具有自己特有的逻辑相等
  • 重写equals的约定:
    • 自反性:x.equals(x)=true
      • 如果违反了自反性,在使用集合的contains方法时会出现问题
    • 对称性:x.equals(y)=y.equals(x)
    • 传递性:x.equals(y)=y.equals(z)=x.equals(z)
    • 一致性:x.equals(y)总是一致的返回一个结果
      • 不要使equals方法依赖于一个不可靠的资源
    • x.equals(null)=false
  • 实现equals方法的诀窍:
    • 使用==操作符检查“参数是否为这个对象的引用”
    • 使用instanceof操作符检查“参数是否为正确的类型”
    • 把参数转换成正确的类型
    • 对于该类中的每一个关键属性进行逐个检查
  • 一些告诫:
    • [[#覆盖equals时总要覆盖hashCode]]
    • 不要企图让equals过于智能
    • 不要将equals声明中的Object对象替换为其他类型
  • 使用IDE生成equals方法

覆盖equals时总要覆盖hashCode

  • 相等的对象(equals)必须具有相同的散列码
  • 一个好的散列函数:不同对象产生不相同的散列码
  • 简单的解决方法:
    • 声明一个int result,将其初始化为对象中第一个关键域的散列码c
    • 接下来计算其他关键域的散列码:
      • 基本类型:使用Type.hashCode()
      • 对象引用:递归调用其中的hashCode()
      • 数组:对其中的每一个元素对计算一次散列码
    • 合并到result
    • 返回result
  • 不要试图从散列码计算中排除掉一个关键域来提高性能

始终要覆盖toString方法

  • 默认的toString方法:类名称@散列码
  • 我们所需要的toString方法:具有简洁的信息,并且易于阅读
  • 返回的String中应该包含所有重要的信息

谨慎的覆盖clone

  • 如果一个类实现了Cloneable接口,那么Object clone()方法就会返回该对象的逐域拷贝,否则抛出CloneNotSupportException异常
  • 实现Cloneable接口的类是为了提供一个功能适当的公有clone方法
  • 不可变的类永远都不应该提供clone方法
  • 对象拷贝的更好方法是提供一个拷贝构造器拷贝工厂