我有一个简单的setter方法的属性和空是不适合这个特定的属性。在这种情况下,我总是被撕裂:我应该抛出一个IllegalArgumentException,还是一个NullPointerException?从javadocs来看,两者都很合适。是否存在某种公认的标准?或者这只是其中一件事,你应该做任何你喜欢做的事情,两种都是正确的?
当前回答
作为一个主观问题,这应该是封闭的,但它仍然是开放的:
这是我以前工作的地方使用的内部政策的一部分,效果非常好。这些都是我的记忆,所以我不记得确切的措辞。值得注意的是,他们没有使用受控异常,但这超出了问题的范围。他们使用的未检查异常主要分为3类。
NullPointerException:不故意抛出。npe只有在解引用空引用时才会被VM抛出。要尽一切可能的努力确保这些错误永远不会被抛出。@Nullable和@NotNull应该与代码分析工具一起使用来发现这些错误。
IllegalArgumentException:当函数的参数不符合公共文档时抛出,这样就可以根据传入的参数识别和描述错误。OP的情况就属于这一类。
IllegalStateException:当调用函数时,其实参在传递时是意外的,或者与方法所属对象的状态不兼容时抛出。
例如,在有长度的事物中使用IndexOutOfBoundsException的两个内部版本。一个是IllegalStateException的子类,在索引大于长度时使用。另一个是IllegalArgumentException的子类,用于索引为负的情况。这是因为您可以向对象添加更多的项,并且参数将是有效的,而负数永远无效。
正如我所说,这个系统工作得非常好,有人解释了为什么会有这样的区别:“根据错误的类型,你很容易就能弄清楚该怎么做。即使您无法真正找出出错的地方,也可以找出在哪里捕获错误并创建额外的调试信息。”
NullPointerException:处理Null情况或放入断言,这样NPE就不会被抛出。如果你输入的断言只是另外两种类型中的一种。如果可能,继续调试,就像断言一开始就在那里一样。
IllegalArgumentException:你的调用站点有错误。如果传入的值来自另一个函数,请查明为什么接收到不正确的值。如果传入一个参数,则会在调用堆栈中进行错误检查,直到找到没有返回预期值的函数。
您没有按照正确的顺序调用函数。如果您正在使用其中一个参数,请检查它们并抛出IllegalArgumentException描述该问题。然后,您可以在堆栈上传播腮部,直到找到问题。
不管怎样,他的观点是你只能把IllegalArgumentAssertions复制到堆栈上。您无法将illegalstateexception或nullpointerexception传播到堆栈上,因为它们与您的函数有关。
其他回答
Apache Commons Lang有一个NullArgumentException,它完成了这里讨论的许多事情:它扩展了IllegalArgumentException,并且它唯一的构造函数采用了参数的名称,而参数的名称本应该是非空的。
虽然我觉得抛出NullArgumentException或IllegalArgumentException之类的异常更准确地描述了异常情况,但我和同事们还是选择遵从Bloch在这个问题上的建议。
抛出一个排除空参数的异常(无论是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.
我倾向于遵循JDK库的设计,特别是集合和并发(Joshua Bloch, Doug Lea,这些人知道如何设计可靠的api)。不管怎样,JDK中的许多api都会主动抛出NullPointerException。
例如,Javadoc For Map。containsKey状态:
如果键为空,则@抛出NullPointerException 不允许空键(可选)。
举办自己的NPE是完全合理的。约定是在异常消息中包含为空的参数名。
模式是这样的:
public void someMethod(Object mustNotBeNull) {
if (mustNotBeNull == null) {
throw new NullPointerException("mustNotBeNull must not be null");
}
}
无论您做什么,都不要允许设置一个错误的值,并在其他代码尝试使用它时抛出异常。这使得调试成为一场噩梦。你应该始终遵循“快速失败”的原则。
以上两个例外的链接定义如下 IllegalArgumentException:抛出该异常,表示方法被传递了一个非法或不适当的参数。 NullPointerException:当应用程序试图在需要对象的情况下使用null时抛出。
这里最大的区别是IllegalArgumentException应该在检查方法的参数是否有效时使用。当一个对象被“使用”为空时,就应该使用NullPointerException。
我希望这能帮助你正确看待这两者。
一般来说,开发人员不应该抛出NullPointerException异常。当代码试图解引用值为null的变量时,运行时将引发此异常。因此,如果你的方法想要显式禁止null,而不是恰好有一个空值引发一个NullPointerException,你应该抛出一个IllegalArgumentException。
推荐文章
- Java 8接口方法中不允许“同步”的原因是什么?
- 如何找到Java堆大小和内存使用(Linux)?
- 使用Enum实现单例(Java)
- RabbitMQ与通道和连接之间的关系
- buildSessionFactory()配置方法在Hibernate中已弃用?
- Spring MVC -如何获得所有的请求参数在一个地图在Spring控制器?
- 如何在Java中按两个字段排序?
- Android -如何覆盖“后退”按钮,所以它不完成()我的活动?
- 文件之间的差异。路径中的分隔符和斜杠
- 为什么不使用异常作为常规的控制流呢?
- 在方法参数中使用NotNull注释
- Spring MVC中处理可选参数的@RequestParam
- Tomcat:如何查找正在运行的Tomcat版本?
- “java”、“javaw”和“javaws”之间有什么区别?
- 将Date对象转换为日历对象