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


当前回答

一般来说,开发人员不应该抛出NullPointerException异常。当代码试图解引用值为null的变量时,运行时将引发此异常。因此,如果你的方法想要显式禁止null,而不是恰好有一个空值引发一个NullPointerException,你应该抛出一个IllegalArgumentException。

其他回答

我完全赞成为空参数抛出IllegalArgumentException,直到今天,当我注意到Java 7中的Java .util. objects . requirenonnull方法时。用这种方法,而不是做:

if (param == null) {
    throw new IllegalArgumentException("param cannot be null.");
}

你可以:

Objects.requireNonNull(param);

如果你传递给它的参数为空,它会抛出一个NullPointerException。

考虑到这个方法正好在java的中间。util我认为它的存在是一个非常强烈的迹象,抛出NullPointerException是“Java做事的方式”。

我想我已经决定了。

注意,关于硬调试的参数是虚假的,因为您当然可以向NullPointerException提供一条消息,说明什么是null,以及为什么它不应该是null。就像IllegalArgumentException。

One added advantage of NullPointerException is that, in highly performance critical code, you could dispense with an explicit check for null (and a NullPointerException with a friendly error message), and just rely on the NullPointerException you'll get automatically when you call a method on the null parameter. Provided you call a method quickly (i.e. fail fast), then you have essentially the same effect, just not quite as user friendly for the developer. Most times it's probably better to check explicitly and throw with a useful message to indicate which parameter was null, but it's nice to have the option of changing that if performance dictates without breaking the published contract of the method/constructor.

抛出一个排除空参数的异常(无论是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.

我完全同意你说的话。早失败,快失败。非常好的异常咒语。

抛出哪个Exception主要是个人喜好的问题。在我看来,IllegalArgumentException似乎比使用NPE更具体,因为它告诉我问题是我传递给方法的参数,而不是执行方法时可能生成的值。

我的2美分

在这种情况下,IllegalArgumentException使用API向用户传达了“不应该为空”的明确信息。正如其他论坛用户指出的那样,只要你使用API向用户传达正确的信息,你就可以使用NPE。

GaryF和tweak放弃了“有效Java”(我发誓)的参考,建议使用NPE。看看其他好的API是如何构造的,这是了解如何构造你的API的最好方法。

Another good example is to look at the Spring APIs. For example, org.springframework.beans.BeanUtils.instantiateClass(Constructor ctor, Object[] args) has a Assert.notNull(ctor, "Constructor must not be null") line. org.springframework.util.Assert.notNull(Object object, String message) method checks to see if the argument (object) passed in is null and if it is it throws a new IllegalArgumentException(message) which is then caught in the org.springframework.beans.BeanUtils.instantiateClass(...) method.

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