我有一个简单的setter方法的属性和空是不适合这个特定的属性。在这种情况下,我总是被撕裂:我应该抛出一个IllegalArgumentException,还是一个NullPointerException?从javadocs来看,两者都很合适。是否存在某种公认的标准?或者这只是其中一件事,你应该做任何你喜欢做的事情,两种都是正确的?
当前回答
一些集合假设使用NullPointerException而不是IllegalArgumentException拒绝null。例如,如果你比较一个包含null的集合和一个拒绝null的集合,第一个集合将调用另一个集合的containsAll,并捕获它的NullPointerException——而不是IllegalArgumentException。(我正在查看AbstractSet.equals的实现。)
You could reasonably argue that using unchecked exceptions in this way is an antipattern, that comparing collections that contain null to collections that can't contain null is a likely bug that really should produce an exception, or that putting null in a collection at all is a bad idea. Nevertheless, unless you're willing to say that equals should throw an exception in such a case, you're stuck remembering that NullPointerException is required in certain circumstances but not in others. ("IAE before NPE except after 'c'...")
类似地,构建工具可以自动插入空检查。值得注意的是,Kotlin的编译器在向Java API传递可能为空的值时执行此操作。当检查失败时,结果是NullPointerException。因此,为了给所有的Kotlin用户和Java用户提供一致的行为,您需要使用NullPointerException。
其他回答
理想情况下,不应该抛出运行时异常。应该为您的场景创建一个受控异常(业务异常)。因为如果这些异常中的任何一个被抛出并记录下来,它就会误导开发人员在查看日志时。相反,业务异常不会造成这种恐慌,并且在故障排除日志时通常会被忽略。
如果它是一个setter方法,并且null被传递给它,我认为抛出一个IllegalArgumentException会更有意义。NullPointerException似乎在尝试实际使用null的情况下更有意义。
如果你在使用它,它是空的,NullPointer。如果它被传入并且它为空,则为非法参数。
Apache Commons Lang有一个NullArgumentException,它完成了这里讨论的许多事情:它扩展了IllegalArgumentException,并且它唯一的构造函数采用了参数的名称,而参数的名称本应该是非空的。
虽然我觉得抛出NullArgumentException或IllegalArgumentException之类的异常更准确地描述了异常情况,但我和同事们还是选择遵从Bloch在这个问题上的建议。
如果你不希望null是一个允许的值,似乎会调用IllegalArgumentException,如果你试图使用一个结果为null的变量,则会抛出NullPointerException。
我倾向于遵循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");
}
}
无论您做什么,都不要允许设置一个错误的值,并在其他代码尝试使用它时抛出异常。这使得调试成为一场噩梦。你应该始终遵循“快速失败”的原则。
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap