我有一个简单的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。
其他回答
二分法……它们不重叠吗?只有整体中不重叠的部分才能构成二分法。在我看来:
throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));
标准是抛出NullPointerException。通常不会出错的“有效Java”在第42项(第一版)、第60项(第二版)或第72项(第三版)中简要讨论了这一点。“赞成使用标准异常”:
可以说,都是错误的方法 调用归结为非法 争论或非法国家,但其他 异常通常用于 一些不合法的论点 州。如果调用方传入null 某个参数,其值为空 是被禁止的吗 NullPointerException被抛出 而不是IllegalArgumentException。”
一般来说,开发人员不应该抛出NullPointerException异常。当代码试图解引用值为null的变量时,运行时将引发此异常。因此,如果你的方法想要显式禁止null,而不是恰好有一个空值引发一个NullPointerException,你应该抛出一个IllegalArgumentException。
如果你不希望null是一个允许的值,似乎会调用IllegalArgumentException,如果你试图使用一个结果为null的变量,则会抛出NullPointerException。
实际上,在我看来,抛出IllegalArgumentException或NullPointerException的问题只是对Java中不完全理解异常处理的少数人的“圣战”。一般来说,规则很简单,如下:
argument constraint violations must be indicated as fast as possible (-> fast fail), in order to avoid illegal states which are much harder to debug in case of an invalid null pointer for whatever reason, throw NullPointerException in case of an illegal array/collection index, throw ArrayIndexOutOfBounds in case of a negative array/collection size, throw NegativeArraySizeException in case of an illegal argument that is not covered by the above, and for which you don't have another more specific exception type, throw IllegalArgumentException as a wastebasket on the other hand, in case of a constraint violation WITHIN A FIELD that could not be avoided by fast fail for some valid reason, catch and rethrow as IllegalStateException or a more specific checked exception. Never let pass the original NullPointerException, ArrayIndexOutOfBounds, etc in this case!
至少有三个非常好的理由反对将所有类型的参数约束违反映射到IllegalArgumentException,第三个理由可能非常严重,以至于标志着这种做法的糟糕风格:
(1) A programmer cannot a safely assume that all cases of argument constraint violations result in IllegalArgumentException, because the large majority of standard classes use this exception rather as a wastebasket if there is no more specific kind of exception available. Trying to map all cases of argument constraint violations to IllegalArgumentException in your API only leads to programmer frustration using your classes, as the standard libraries mostly follow different rules that violate yours, and most of your API users will use them as well!
(2) Mapping the exceptions actually results in a different kind of anomaly, caused by single inheritance: All Java exceptions are classes, and therefore support single inheritance only. Therefore, there is no way to create an exception that is truly say both a NullPointerException and an IllegalArgumentException, as subclasses can only inherit from one or the other. Throwing an IllegalArgumentException in case of a null argument therefore makes it harder for API users to distinguish between problems whenever a program tries to programmatically correct the problem, for example by feeding default values into a call repeat!
(3) Mapping actually creates the danger of bug masking: In order to map argument constraint violations into IllegalArgumentException, you'll need to code an outer try-catch within every method that has any constrained arguments. However, simply catching RuntimeException in this catch block is out of the question, because that risks mapping documented RuntimeExceptions thrown by libery methods used within yours into IllegalArgumentException, even if they are no caused by argument constraint violations. So you need to be very specific, but even that effort doesn't protect you from the case that you accidentally map an undocumented runtime exception of another API (i.e. a bug) into an IllegalArgumentException of your API. Even the most careful mapping therefore risks masking programming errors of other library makers as argument constraint violations of your method's users, which is simply hillareous behavior!
With the standard practice on the other hand, the rules stay simple, and exception causes stay unmasked and specific. For the method caller, the rules are easy as well: - if you encounter a documented runtime exception of any kind because you passed an illegal value, either repeat the call with a default (for this specific exceptions are neccessary), or correct your code - if on the other hand you enccounter a runtime exception that is not documented to happen for a given set of arguments, file a bug report to the method's makers to ensure that either their code or their documentation is fixed.
推荐文章
- 在JavaScript中,什么相当于Java的Thread.sleep() ?
- 使用Java重命名文件
- URL从Java中的类路径加载资源
- 我如何让红宝石打印一个完整的回溯而不是截断一个?
- .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?
- Hibernate中不同的保存方法之间有什么区别?
- Visual Studio:如何打破处理异常?
- Java 8流和数组操作
- Java Regex捕获组
- Openssl不被视为内部或外部命令
- 如何添加自定义方法到Spring Data JPA
- 如何在Ubuntu中设置Java环境路径
- 无法执行dex:在Eclipse中超过GC开销限制
- 有人能解释一下JPA和Hibernate中的mappedBy吗?
- 无法加载文件或程序集…参数不正确