我遇到了下面的代码,我希望Java能够通过一个异常,因为我要迭代的列表为空。
public static void main(String[] args) {
final List<Map<String, Object>> candidateList = new ArrayList<>();
for (final Map<String, Object> candidate : candidateList) {
if (candidate.isEmpty()) {
System.out.println("Empty!!!");
}
}
}
但是代码执行时没有抛出任何错误或异常。
答案 0 :(得分:2)
您正在使用增强了循环功能:
for (final Map<String, Object> candidate : candidateList) {
...
}
编译器将其替换为与以下源代码等效的字节码:
Iterator<Map<String, Object>> elementIter = candidateList.iterator();
while (elementIter.hasNext()) {
final Map<String, Object> candidate = elementIter.next();
...
}
如果elementIter.next()
确实会抛出NoSuchElementException
(如果再也没有下一个元素的话)(请参阅documentation),则首先检查循环条件:
while (elementIter.hasNext()) {
根据您的情况,Iterator#hasNext
返回false
。参见documentation:
如果迭代具有更多元素,则返回
true
。 (换句话说,如果true
将返回一个元素而不是引发异常,则返回next()
。)
因此您的循环从未输入。这就是为什么您不会看到循环设计者所希望的任何异常的原因。
为进行比较,让我们尝试使用常规循环迭代空数组:
int[] values = new int[0];
for (int i = 0; i < values.length; i++) {
System.out.println(values[i]);
}
由于与以前相同的原因,代码可以正常运行,没有任何异常。条件解决
i < 0
第一次迭代(i = 0
)已经为假。因此永远不会进入循环。
这意味着增强的循环的行为与本例中常规循环的行为相同。
答案 1 :(得分:0)
public static void main(String[] args) {
final List<Map<String, Object>> candidateList = new ArrayList<>();
for (final Map<String, Object> candidate : candidateList) {
//because all below code will never execute
if (candidate.isEmpty()) {
System.out.println("Empty!!!");
}
}
}
它永远不会进入循环,因此不会引发任何异常。
如果将null元素添加到列表中。会抛出错误
答案 2 :(得分:0)
库设计者决定不引发异常,因为他们认为这将使使用库清理器的代码成为可能。如果确实引发了异常,则您每次都必须检查集合是否为空,而不是仅对其进行迭代并且不依赖任何内容。
设计师在不同情况下做出了不同的决定。例如,如果不存在与谓词匹配的元素,则Guava的Iterables.find(iterable, predicate)
会引发异常,此时它可能刚刚返回了null
,等等。
用于决定是否引发异常的经验法则是这样的:如果使用参数进行的调用很可能是由错误引起的,或者可能造成难以调试的错误,则引发异常。否则,请做一些明智的事情(例如返回null
,禁止操作等)
因此,尝试迭代一个空的集合被认为不太可能是错误的,而试图找到一个集合中不存在的元素可能被认为是意料之外的,因此有例外。但是,这些规则并不是一成不变的规则,并且不同语言,不同设计师,不同案例的观点也有所不同。