【发布时间】:2010-06-12 12:48:32
【问题描述】:
请大家告诉我,在现实世界中,为什么我们需要重写 equals 和 hashcode 而我们不能使用 Object 的 equals 和 hashcode。
【问题讨论】:
-
@skaffman:我认为“有什么陷阱”和“我们为什么需要这样做”是不同的问题。
-
@jon 是的,这就是我想问的问题
请大家告诉我,在现实世界中,为什么我们需要重写 equals 和 hashcode 而我们不能使用 Object 的 equals 和 hashcode。
【问题讨论】:
对象的 equals/hashcode 实现很好 - 如果您希望“引用标识”作为您的相等性。换句话说,一个对象总是会与自己比较,但与另一个对象不同。
但是,如果您希望两个不同的对象相等,则必须重写方法以说明 如何 它们应该相等(然后重写哈希码以使其保持一致)。
最简单的例子可能是字符串。两个具有相同字符的不同字符串相等,让它们相等非常有用:
String x = new String(new char[]{'a', 'b', 'c'});
String y = new String(new char[]{'a', 'b', 'c'});
System.out.println(x.equals(y)); // Prints true
现在将其与FileInputStream 进行比较 - 什么会使两个 FileInputStreams 相等?如果他们正在读取同一个文件?文件中的位置呢?两个流到具有相同内容的不同文件呢? IMO,问这个问题并没有多大意义。
现在,Object 实现如何知道FileInputStream 和String 所需行为之间的区别?它可能可能会注意添加到字段、属性和类型本身的注释,可能会自动生成适当的字节码,然后可以进行 JIT 编译......但当然,Java 早在注释可用之前就出现了。当前的方法非常简单 - 但它确实意味着如果您想要不同对象的值相等,您需要自己编写代码。
需要注意的一点是,对于不可变类型来说,相等通常更容易考虑——如果两个对象在某个时间点相等,但后来又不相等,这很奇怪。这也可能严重破坏哈希表 - 哈希码应该基本上取决于考虑相等的对象的方面,并且哈希码是在第一次将键添加到哈希表时记录的;如果你随后更改键的内容,它的哈希码会改变,但哈希表不会知道它。
【讨论】:
因为在real world如果你使用Object的实现
new Integer( 1 ) 不等于 new Integer( 1 )
【讨论】: