为什么在Java中迭代Empty Map不会引发任何异常

时间:2018-10-14 11:48:50

标签: java

我遇到了下面的代码,我希望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!!!");
        }
    }
}

但是代码执行时没有抛出任何错误或异常。

3 个答案:

答案 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,禁止操作等)

因此,尝试迭代一个空的集合被认为不太可能是错误的,而试图找到一个集合中不存在的元素可能被认为是意料之外的,因此有例外。但是,这些规则并不是一成不变的规则,并且不同语言,不同设计师,不同案例的观点也有所不同。