【发布时间】:2011-02-22 16:26:29
【问题描述】:
equals与null的合约如下:
对于任何非空引用值
x,x.equals(null)应为return false。
这很奇怪,因为如果o1 != null 和o2 == null,那么我们有:
o1.equals(o2) // returns false
o2.equals(o1) // throws NullPointerException
o2.equals(o1) throws NullPointerException 是一件好事,因为它提醒我们程序员的错误。然而,如果出于各种原因我们只是将其切换为 o1.equals(o2),则不会捕获该错误,而这只会“静默失败”。
所以问题是:
- 为什么
o1.equals(o2)应该return false而不是抛出NullPointerException是个好主意? - 如果我们尽可能重写合约以便
anyObject.equals(null)总是抛出NullPointerException,那会不会是个坏主意?
与Comparable比较
相比之下,Comparable contract 是这样说的:
注意
null不是任何类的实例,e.compareTo(null)应该抛出一个NullPointerException,即使e.equals(null)返回false。
如果NullPointerException 适用于compareTo,为什么不适用于equals?
相关问题
纯语义论证
这些是Object.equals(Object obj) 文档中的实际用词:
指示某个其他对象是否“等于”这个对象。
什么是对象?
JLS 4.3.1 Objects
一个对象是一个类实例或一个数组。
引用值(通常只是references)是指向这些对象的指针,以及一个特殊的
null引用,没有引用任何对象。
这个角度我的论点很简单。
-
equals测试某些 other 对象 是否“等于”this -
null参考没有提供 其他对象 用于测试 - 因此,
equals(null)应该抛出NullPointerException
【问题讨论】:
-
在此评论说,众所周知,在 Java 中,equals() 出现在 OO 层次结构的最顶层,这是不可能 尊重除了最简单的情况以外的任何事情的等价合同(即当你根本不做 OO 时)。认为存在诸如未损坏的 Java equals() 合约之类的东西是一种妄想。我们走得更远:默认情况下 equals() 和 hashCode() 会抛出 UOE。如果您想使用这些方法,您必须记录您如何处理此处提出的基本问题:artima.com/lejava/articles/equality.html
-
8 票和 3 个最爱我的问题与 equals 的无可争辩的破碎有关:stackoverflow.com/questions/2205565 问题是:“共同等于智慧”根本行不通.不仅像 Joshua Bloch 和 Martin Odersky 这样的人这么说,而且你可以用逻辑来证明这一事实。您根本无法进行 OOA/OOD 到 OOP 的转换,并希望重用 Java 的相等概念:对我来说,equals 存在于 Object 中是语言的一个根本缺陷。当然,喝 Gosling kool-aid 的人会不同意。让他们和布洛赫争论
-
我的最后一点是:在许多情况下,这不是关于抛出 NPE 或返回 false:而是关于抛出一个巨大的 UnsupportedOperationException 并且它是一个 Java 缺陷,允许在对象上调用 equals,这些对象一开始就不应该有相等的概念。著名的遗言:UnsupportedOperationException :)
标签: java null equals nullpointerexception