合同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
合同说:
需要注意的是null
不是任何类的实例,并e.compareTo(null)
应该抛出一个NullPointerException
,即使e.equals(null)
将返回false
。
如果NullPointerException
适合compareTo
,为什么不是它equals
?
相关问题
一个纯粹的语义争论
这些都是在实际的话Object.equals(Object obj)
的文件:
指示某个其他对象是否“等于”这一项。
什么是对象?
JLS 4.3.1对象
对象是类的实例或阵列。
的参考值(通常仅引用 )是指向这些对象,和一个特殊的null
引用,这是指没有对象 。
从这个角度我的论点是非常简单的。
-
equals
测试是否其他对象 “等于” this
-
null
参考没有给出其他对象用于测试 - 因此,
equals(null)
应该抛出NullPointerException
Answer 1:
要的这种不对称是不一致的问题,我觉得不是,我是指你这个古老的禅宗公案:
- 问任何一个人,如果他作为一个男人的好,每次都会说是的。
- 问任何一个人,如果他是因为没有人好而且每次都会说不。
- 询问任何人,如果它是任何人一样好,你永远不会得到答复。
在那一刻,编译器达到了启示。
Answer 2:
例外实在是一个特殊情况。 一个空指针可能不是一个程序员的错误。
你报的现有合同。 如果您决定违背惯例,毕竟这个时候,当每一个Java开发人员预计,等于返回false,你会做什么意外和不受欢迎的,这将使你的类贱民。
我不同意便无法更多。 我不会改写等于抛出异常的所有时间。 我想更换做了,如果我是它的客户端的任何类。
Answer 3:
想的.equals是如何==相关和.compareTo涉及比较运算符>,<,> =,<=。
如果你要认为使用.equals比较对象为null应该抛出一个NPE,那么你不得不说,这个码应该抛出一个还有:
Object o1 = new Object();
Object o2 = null;
boolean b = (o1 == o2); // should throw NPE here!
o1.equals(O2)和o2.equals(01)之间的区别是,在第一种情况下,你要比较的东西为null,类似于O1 O2 ==,而在第二种情况下, 不会真正执行equals方法所以没有比较发生在所有。
关于.compareTo合同,与空对象与非空的对象,就像试图做到这一点:
int j = 0;
if(j > null) {
...
}
显然,这将无法编译。 您可以使用自动拆箱,使其编译,但你得到一个NPE,当你做比较,这与.compareTo合同是一致的:
Integer i = null;
int j = 0;
if(j > i) { // NPE
...
}
Answer 4:
不,这是一个neccessarily回答你的问题,它只是当我觉得它有用的行为是现在是如何的一个例子。
private static final String CONSTANT_STRING = "Some value";
String text = getText(); // Whatever getText() might be, possibly returning null.
按照现在的情况,我可以做的。
if (CONSTANT_STRING.equals(text)) {
// do something.
}
我没有得到一个NullPointerException异常的机会。 如果如你所说改了,我会回不得不做:
if (text != null && text.equals(CONSTANT_STRING)) {
// do something.
}
这是一个足够好的理由行为是因为它是? 我不知道,但它是一个有用的副作用。
Answer 5:
如果你把面向对象的概念考虑,并考虑整个发送者和接收者的角色,我会说这种行为是方便。 见在第一种情况下你问的对象,如果他是等于没有人。 他应该说“不,我不是。”
尽管在第二种情况下,你没有给任何人一个参考,因此你是不是真的问任何人。 这应该抛出一个异常,第一种情况不应该。
我认为这是唯一的非对称的,如果你有种忘记面向对象和治疗表达为一个数学等式。 然而,在这种模式两端扮演不同的角色,所以它是可以预料的顺序问题。
作为最后一个要点。 当在你的代码中的错误空指针异常应适当提高。 然而,询问的对象,如果他是谁,不应该被视为一种编程缺陷。 我认为这是完全可以问一个对象,如果他不为空。 如果你不控制,为您提供对象来源是什么? 这源向您发送无效。 你会检查对象为空,只有事后看看他们是平等的? 那岂不是更直观,只是比较两个和任何第二对象的比较将无例外地进行?
坦率地说,如果内的身体返回故意空指针异常的equals方法,我会生气。 等于,就是要反对任何形式的物体的使用,所以它不应该是什么它收到这么挑剔。 如果equals方法返回北角,在我心中的最后一件事是,这确实是故意的。 特别考虑到这是一个未经检查的异常。 如果你没有引发NPE一个人就一定要记得调用你的方法,或者更糟糕之前,请务必检查空,环绕在try / catch块等于调用(上帝,我恨try / catch块),但哦。 ..
Answer 6:
就个人而言,我宁愿它执行为它。
所述NullPointerException
识别出的问题是在对正在执行equals操作的对象。
如果NullPointerException
作为你的建议,你尝试过的(那种毫无意义的)操作...
o1.equals(o1)
其中01 =空...是NullPointerException
抛出,因为你比较函数被拧紧或因为O1为空,但你不知道? 一个极端的例子,我知道,但是当前的行为,我觉得可以告诉你问题所在。
Answer 7:
在第一种情况o1.equals(o2)
因为返回false o1
不等于o2
,这是完全没有问题。 在第二种情况下,它会引发NullPointerException
,因为o2
是null
。 一个不能调用上的任何方法null
。 这可能是一般的编程语言的限制,但我们必须接受它。
它也不是扔一个好主意NullPointerException
你违反了合同equals
方法,使事情更复杂的比它必须是。
Answer 8:
有许多地方常见的情况下null
是不以任何方式特殊,例如,它可以简单地表示,其中的关键是没有价值的(非特殊)的情况下,或以其他方式表示“没有”。 因此,做x.equals(y)
与未知y
也相当普遍,且总是检查null
第一将只是无用功。
至于为什么null.equals(y)
是不同的,它是一个编程错误调用任何实例方法在Java中的空引用,因此值得一个例外。 的顺序x
和y
在x.equals(y)
的选择应使得x
是已知的不null
。 我认为,在几乎所有情况下,这种重新排序可以根据已知的关于对象事先(例如,从它们的来源,或对检查进行null
对其他方法调用)。
同时,如果两个对象都是未知“NULL的含量”的,那么其他的代码几乎可以肯定需要检查它们中的至少一个,或者没有多少可与该对象来完成,而不用担心了NullPointerException
。
而且,由于这是它被指定的方式,这是一个编程错误撕毁合同并引发异常的null
参数equals
。 如果你考虑要求异常的替代品被抛出,那么每实现equals
将不得不作出它的一个特殊情况,并且每次调用equals
与任何潜在的null
对象必须调用前检查。
它可能已被指定不同的(即的前提equals
需要的参数为非null
),所以这是不是说你的论点是无效的,但目前的规范使得一个更简单,更实用的编程语言。
Answer 9:
需要注意的是该合同“对于任何非空引用X”。 因此,实施将是这样的:
if (x != null) {
if (x.equals(null)) {
return false;
}
}
x
不一定是null
被视为等于null
,因为下面的定义equals
是可能的:
public boolean equals(Object obj) {
// ...
// If someMember is 0 this object is considered as equal to null.
if (this.someMember == 0 and obj == null) {
return true;
}
return false;
}
Answer 10:
我认为这是关于便利,更重要的一致性-允许空值成为比较的一部分避免了做一个null
检查和落实,每次语义equals
被调用。 null
引用在许多集合类型的法律,所以它使它们可以显示为比较的右侧感。
使用实例方法平等,比较等,一定让安排不对称 - 为多态性的巨大增益有点麻烦。 当我不需要多态,我有时会创建两个参数,一个对称的静态方法MyObject.equals(MyObjecta, MyObject b)
然后,这个方法检查一个或两个参数是否空引用。 如果我特别要排除空引用,然后创建一个额外的方法如equalsStrict()
或类似的,那确实委托给其他方法实施前的空检查。
Answer 11:
这是一个棘手的问题。 对于向后兼容性,你不能这样做。
想象一下以下情形
void m (Object o) {
if (one.equals (o)) {}
else if (two.equals (o)) {}
else {}
}
现在与equals返回false else子句会得到执行,而不是抛出一个异常时。
也为空是不是真的等于说“2”,所以它非常有意义返回false。 然后,它可能是更好地坚持null.equals(“B”)也返回false :))
但是,这个要求确实让一个奇怪的和非对称等于关系。
文章来源: Is it a bad idea if equals(null) throws NullPointerException instead?