我有一个简单的setter方法的属性和空是不适合这个特定的属性。在这种情况下,我总是被撕裂:我应该抛出一个IllegalArgumentException,还是一个NullPointerException?从javadocs来看,两者都很合适。是否存在某种公认的标准?或者这只是其中一件事,你应该做任何你喜欢做的事情,两种都是正确的?


当前回答

当试图访问具有当前值为null的引用变量的对象时,抛出NullPointerException。

当方法接收到格式与方法预期不同的参数时,抛出IllegalArgumentException。

其他回答

根据您的场景,IllegalArgumentException是最好的选择,因为null不是属性的有效值。

二分法……它们不重叠吗?只有整体中不重叠的部分才能构成二分法。在我看来:

throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));

你应该使用IllegalArgumentException (IAE),而不是NullPointerException (NPE),原因如下:

首先,NPE JavaDoc显式地列出了适用于NPE的情况。请注意,当不恰当地使用null时,所有这些都是由运行时抛出的。相比之下,IAE JavaDoc再清楚不过了:“抛出是为了表明一个方法被传递了一个非法或不适当的参数。”没错,就是你!

其次,当您在堆栈跟踪中看到NPE时,您会假设什么?可能有人解引用了一个null。当您看到IAE时,您假定堆栈顶部的方法调用方传递了一个非法值。同样,后一种假设是正确的,前一种假设具有误导性。

第三,由于IAE显然是为验证参数而设计的,因此必须假设它是默认的异常选择,那么为什么要选择NPE呢?当然不是针对不同的行为——你真的期望调用代码分别捕获NPE和IAE,并因此做一些不同的事情吗?您是否试图传达更具体的错误消息?但是无论如何,您都可以在异常消息文本中这样做,就像处理所有其他不正确的参数一样。

第四,其他所有不正确的参数数据都会被IAE,为什么不一致呢?为什么非法null是如此特殊,以至于它应该从所有其他类型的非法参数中获得一个单独的异常?

最后,我接受其他答案给出的论点,即Java API的某些部分以这种方式使用NPE。然而,从异常类型到命名约定,Java API与所有内容都不一致,因此我认为仅仅盲目地复制(您最喜欢的部分)Java API并不是一个足以胜过这些其他考虑因素的好理由。

抛出一个排除空参数的异常(无论是NullPointerException还是自定义类型)使得自动化空测试更加可靠。这种自动化测试可以通过反射和一组默认值来完成,就像在Guava的NullPointerTester中一样。例如,NullPointerTester将尝试调用以下方法…

Foo(String string, List<?> list) {
  checkArgument(string.length() > 0);
  // missing null check for list!
  this.string = string;
  this.list = list;
}

...with two lists of arguments: "", null and null, ImmutableList.of(). It would test that each of these calls throws the expected NullPointerException. For this implementation, passing a null list does not produce NullPointerException. It does, however, happen to produce an IllegalArgumentException because NullPointerTester happens to use a default string of "". If NullPointerTester expects only NullPointerException for null values, it catches the bug. If it expects IllegalArgumentException, it misses it.

如果你不希望null是一个允许的值,似乎会调用IllegalArgumentException,如果你试图使用一个结果为null的变量,则会抛出NullPointerException。