我有一个简单的setter方法的属性和空是不适合这个特定的属性。在这种情况下,我总是被撕裂:我应该抛出一个IllegalArgumentException,还是一个NullPointerException?从javadocs来看,两者都很合适。是否存在某种公认的标准?或者这只是其中一件事,你应该做任何你喜欢做的事情,两种都是正确的?
当前回答
这是一个“圣战”式的问题。换句话说,两种选择都是好的,但人们会有自己的偏好,他们会誓死捍卫这些偏好。
其他回答
根据您的场景,IllegalArgumentException是最好的选择,因为null不是属性的有效值。
抛出一个排除空参数的异常(无论是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.
这是一个“圣战”式的问题。换句话说,两种选择都是好的,但人们会有自己的偏好,他们会誓死捍卫这些偏好。
实际上,在我看来,抛出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.
如果你不希望null是一个允许的值,似乎会调用IllegalArgumentException,如果你试图使用一个结果为null的变量,则会抛出NullPointerException。
推荐文章
- 如何格式化Joda-Time DateTime仅为mm/dd/yyyy?
- 如何获取在Python中捕获的异常的名称?
- 如何在POM.xml中引用环境变量?
- 如何在android中复制一个文件?
- 将整数转换为字符串,以逗号表示千
- 接口方法的最终参数-有什么意义?
- Java中的@UniqueConstraint注释
- 如何在清洁模式下运行eclipse ?如果我们这样做会发生什么?
- 获取java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory异常
- Java中的正则表达式命名组
- c#和Java的主要区别是什么?
- 什么是NullPointerException,我如何修复它?
- 在Java中使用“final”修饰符
- 无法在Flutter上找到捆绑的Java版本
- 如何在Kotlin解析JSON ?