参考文章:深入理解java异常处理机制


假设前提背景有:

int i = 0;
String greetings[] = { " Hello world !", " Hello World !! ", " HELLO WORLD !!!" };

1、因 try-catch 造成的死循环

(1)

while (i < 4) {
    try {
        System.out.println(greetings[i]);
        i++;
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("数组下标越界异常 " + i);
    } finally {
        System.out.println("--------------------------");
    }
}

对于上述逻辑,是为造成死循环的。打印结果如下:

java死循环里的new 怎么释放 java死循环报什么异常_java死循环里的new 怎么释放


程序会在之后一直(循环)打印:

数组下标越界异常 3
--------------------------

陷入死循环的原因:

因为当 i == 2 时,执行完 i++,此时 i == 3,然后 greetings[i] 会造成数组越界异常,此时会被 catch 掉,因此不会再执行到 i++(即 i 不会为 4),接下来执行了 finally 就会进入下一次循环(因为 i 为 3 小于 4),而执行到 greetings[i] 又出现异常,又不会执行 i++,从而陷入死循环。

(2)

而如果将:

System.out.println(greetings[i]);
i++;

改成

greetings[i++]

即把两句合为一句,则不会出现死循环。

因为此时会执行完 i++(使 i 达到 4) 再被 catch,因此会不满足 while 条件而退出循环。打印结果如下:

java死循环里的new 怎么释放 java死循环报什么异常_死循环_02

(3)
或者,将 try-catch 语句放在最外层。

try {
    while (i < 4) {
        System.out.println(greetings[i]);
        i++;
    }
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("数组下标越界异常 " + i);
    return;
} finally {
    System.out.println("--------------------------");
}

不会出现死循环,因为当 i == 3 时,会因异常退出整个 while 循环。打印结果如下:

java死循环里的new 怎么释放 java死循环报什么异常_i++_03


此时,如果也将那两句合并为 System.out.println(greetings[i++]),则打印结果为 4。

java死循环里的new 怎么释放 java死循环报什么异常_i++_04


2、return 与 finally

首先需要明确的是,不管有没有发生异常,如果有 finally 语句,则 finally 都会执行。

除非是图中说明的那几种特殊情况:

java死循环里的new 怎么释放 java死循环报什么异常_死循环_05

public static int testException() {
    int i = 0;
    String[] greetings = {" Hello world !", " Hello World !! ",
            " HELLO WORLD !!!"};
    try {
        while (i < 4) {
            System.out.println(greetings[i]);
            i++;
        }
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("数组下标越界异常 " + i);
        return 20;
    } finally {
        // 无论怎么样, finally 都将会执行
        System.out.println("--------------------------");
    }
    // 此时 “return 30” 放在 try-catch-finally 的外面
    return 30;
}

public static void main(String[] args) {
	System.out.println(testException());
}

运行结果:

java死循环里的new 怎么释放 java死循环报什么异常_i++_06


可以看到,在发生异常的前提下,即使在 catch 中 return 了(但是此时 return 30 放在 try-catch-finally 的外面),但是还是会执行 finally 中的逻辑,只不过此时 testException() 方法是 return 的结果是 catch 中的 20。

但是如果是这样,将 return 30 移到 finally 中:

public static int testException() {
    ...
    } finally {
        // 无论怎么样, finally 都将会执行
        System.out.println("--------------------------");
        return 30;
    }
}

则此时 testException() 方法是 return 的结果是 finally 中的 30。

java死循环里的new 怎么释放 java死循环报什么异常_System_07


前面说的是发生异常的前提下,而不管有没有发生异常,如果 finally 中有 return 语句,则之后的逻辑都不会被执行了。如图,可以看到,编译器发出了警告:

java死循环里的new 怎么释放 java死循环报什么异常_i++_08