EffectiveJava笔记(二) 对于所有对象都通用的方法

来源:互联网 发布:iphone作mac 游戏手柄 编辑:程序博客网 时间:2024/06/14 19:14

8. 覆盖equals时请遵守通用约定

  • 类的每个实例本质上都是唯一的

  • 不关心类是否提供了”逻辑相等”的测试功能

  • 超类已经覆盖了equals, 从超类继承过来的行为对子类也是合适的

  • 类是私有的或者包级私有的, 可以确定它的equals方法永远不会被调用

程序员在利用equals方法来比较值对象的引用时, 希望知道它们在逻辑上是否相等, 而不是想了解它们是否指向同一个对象, 为了满足程序员的要求, 不仅必需覆盖equals方法, 而且这样做也使得这个类的实例可以被用做映射表的键, 或者集合的元素, 使映射或集合表现出预期的行为

在覆盖equals方法的时候, 必需遵守它的通用约定, JavaSE6约定规范为:

  • 自反性, 对于任何非null的引用值x, x.equals(x)必须返回true

  • 对称性, 对于任何非null的引用值x和y, 当且仅当y.equals(x)返回true时, x.equals(y)必须返回true

  • 传递性, 对于任何非null的引用值x, y, z, 如果x.equals(y)返回true, 并且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. 使用==操作符检查 “参数是否为这个对象的引用”, 如果是, 则返回true, 这是一种性能优化, 如果比较操作有可能很昂贵, 就值得这么做了
2. 使用instanceof操作符检查”参数是否为正确的类型”
3. 把参数转换为正确的类型, 因为转换之前进行过instanceof测试, 所以确保会成功
4. 对于该类中的每个”关键”域, 检查参数中的域是否与该对象中对应的域相匹配, 对于既不是float也不是dobule类型的基本类型域, 可以使用==操作符进行比较, 对于对象引用域, 可以递归地调用equals方法, 对于float可以用Float.compare方法, double域则使用Double.compare

9. 覆盖equals时总要覆盖hashCode

在每个覆盖了equals方法的类中, 也必需覆盖hashCode方法, 如果不这样做得话, 就会违反Object.hashCode的通用约定, 从而导致该类无法结合所有基于散列的集合一起正常运作, 这样的集合包括HashMap, HashSet和Hashtable, 下面是JavaSE6 Object规范:

  • 在应用程序的执行期间, 只要对象的equals方法的比较操作所用到的信息没有被修改, 那么对着同一个对象调用多次, hashCode方法都必须始终如一地返回同一个整数, 在同一个应用程序的多次执行过程中, 每次执行所返回的整数可以不一致

  • 如果两个对象根据equals(Object)方法比较是相等的, 那么调用这两个对象中任意个对象的hashCode方法都必须产生同样的整数结果

  • 如果两个对象根据equals(Object)方法比较是不相等的, 那么调用这两个对象中任意一个的hashCode方法, 则不一定要产生不同的整数结果, 但是程序员应该知道, 给不相等的对象产生截然不同的整数结果, 有可能提高散列表(hash table)的性能

10. 始终要覆盖toString

虽然不是不需的, toString对开发人员来说打印数据比较方便

11. 考虑实现Comparable接口

类实现了Comparable接口, 就表明它的实例具有内在的排序关系, 为实现Comparable接口得对象数组进行排序, Arrays.sort(a)

  • 实现者必须确保所有的x和y都满足x.compareTo(y) == -y.compareTo(x)

  • 实现者还必须确保这个比较关系是可传递的, (x.compareTo(y) > 0 && y.compareTo(z) > 0)暗示着x.compareTo(z) > 0

  • 实现者必须确保x.compareTo(y) == 0, 暗示着所有的z都满足x.compareTo(z) == y.compareTo(z)

  • 强烈建议 (x.compareTo(y) == 0) == (x.equals(y))

阅读全文
0 0