它是一个糟糕的主意,如果等于(空)抛出NullPointerException异常呢?它是一个糟糕的

2019-05-13 05:11发布

合同equals与问候null ,如下所示:

对于任何非空引用值xx.equals(null)应该return false

这是相当奇怪的,因为如果o1 != nullo2 == 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 ,因为o2null 。 一个不能调用上的任何方法null 。 这可能是一般的编程语言的限制,但我们必须接受它。

它也不是扔一个好主意NullPointerException你违反了合同equals方法,使事情更复杂的比它必须是。



Answer 8:

有许多地方常见的情况下null是不以任何方式特殊,例如,它可以简单地表示,其中的关键是没有价值的(非特殊)的情况下,或以其他方式表示“没有”。 因此,做x.equals(y)与未知y也相当普遍,且总是检查null第一将只是无用功。

至于为什么null.equals(y)是不同的,它一个编程错误调用任何实例方法在Java中的空引用,因此值得一个例外。 的顺序xyx.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?