try-catch-finally 简介¶
在 Java 中,try-catch-finally 语句可用于错误捕获和错误处理。程序员将可能会抛出异常的代码置于 try 块中,使用 catch 来捕获不同类型的错误,并在 catch 块中编写错误处理代码。最后可以使用 finally 块来清理相关资源。
若 try 块内的代码抛出异常,就可能被 catch 捕获到,最后运行 finally;而若 try 中代码不抛出异常,最后也应该运行 finally 块中的代码。
但是在一些特殊情况下,try-catch-finally 代码的顺序变得难以确定。此文为这些可能的特殊情况做了一个简单的整理与总结。
异常情况总结¶
try 中含有 return¶
try 中产生异常¶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| public class withReturn {
public static void main(String[] args) {
System.out.println(catchException());
}
private static void throwException() throws Exception {
throw new Exception("throwing Exception");
}
private static String catchException() {
try {
System.out.println("try block");
throwException();
return "try return";
} catch (Exception e) {
System.out.printf("catch the exception: `%s` in catch block\n", e.toString());
} finally {
System.out.println("finally block");
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
1
2
3
4
| try block
catch the exception: `java.lang.Exception: throwing Exception` in catch block
finally block
outside the try-catch-finally block
|
可见,运行顺序遵循 try -> catch -> finally ,在抛出异常后,会直接运行到 catch 中的语句,而不会运行 try 中的 return 语句。这与我们的预期一致。
try 中不产生异常¶
即:能够运行到 try 中的 return 语句。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| public class withReturn {
public static void main(String[] args) {
System.out.println(noException());
}
private static String noException() {
try {
System.out.println("try block");
return "try return";
} catch (Exception e) {
System.out.printf("catch the exception: `%s` in catch block\n", e.toString());
} finally {
System.out.println("finally block");
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
1
2
3
| try block
finally block
try return
|
可见,当 try 中没有异常抛出时,在 try 中的 return 语句被执行时会运行 finally 中的代码,再返回 try 中 return 语句的返回值。
try, catch, finally 中都有 return¶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| public class withReturn {
public static void main(String[] args) {
System.out.println(allReturn());
}
private static String allReturn() {
try {
System.out.println("try block");
return "try return";
} catch (Exception e) {
System.out.printf("catch the exception: `%s` in catch block\n", e.toString());
return "catch return";
} finally {
System.out.println("finally block");
return "finally return";
}
}
}
|
运行结果为:
1
2
3
| try block
finally block
finally return
|
若 finally 中有 return 语句,则会直接从 finally 中返回结果,try 块中的 return 结果则被丢弃。
catch, finally 抛出异常¶
catch 抛出异常¶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| public class catchFinallyException {
public static void main(String[] args) {
System.out.println(catchThrowException());
}
private static void throwException() throws Exception {
throw new Exception("throwing Exception");
}
private static String catchThrowException() {
try {
System.out.println("try block");
throwException();
} catch (Exception e) {
System.out.printf("catch the exception: `%s` in catch block\n", e.toString());
int a = 2 / 0; // ArithmeticException
System.out.println("catch end");
} finally {
System.out.println("finally block");
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
1
2
3
4
5
6
7
| try block
catch the exception: `java.lang.Exception: throwing Exception` in catch block
finally block
Exception in thread "main" java.lang.ArithmeticException: / by zero
at tryCatchFinally.catchFinallyException.catchThrowException(catchFinallyException.java:18)
at tryCatchFinally.catchFinallyException.main(catchFinallyException.java:5)
|
可见,catch 块在抛出异常后终止,最后 main 线程会抛出异常,但是 finally 块仍然运行。
finally 抛出异常¶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| public class catchFinallyException {
public static void main(String[] args) {
System.out.println(catchFinallyException());
}
private static void throwException() throws Exception {
throw new Exception("throwing Exception");
}
private static String catchFinallyException() {
try {
System.out.println("try block");
throwException();
} catch (Exception e) {
System.out.printf("catch the exception: `%s` in catch block\n", e.toString());
} finally {
System.out.println("finally block");
int a = 2 / 0; // ArithmeticException
System.out.println("finally end");
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
1
2
3
4
5
6
7
| try block
catch the exception: `java.lang.Exception: throwing Exception` in catch block
finally block
Exception in thread "main" java.lang.ArithmeticException: / by zero
at tryCatchFinally.catchFinallyException.catchFinallyException(catchFinallyException.java:20)
at tryCatchFinally.catchFinallyException.main(catchFinallyException.java:5)
|
可见,finally 块运行到抛出异常后终止,最后 main 线程也会抛出异常。
try, catch, finally 中有 continue¶
try 中有 continue¶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| public class withContinue {
public static void main(String[] args) {
System.out.println(tryContinue());
}
private static String tryContinue() {
for (int i = 0; i < 2; i++) {
try {
System.out.println("try block");
continue;
} catch (Exception e) {
System.out.printf("catch the exception: `%s` in catch block\n", e.toString());
} finally {
System.out.println("finally block");
}
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
1
2
3
4
5
| try block
finally block
try block
finally block
outside the try-catch-finally block
|
当代码运行到 try 的 continue 后,执行 finally 块中的逻辑再继续循环。
catch 中有 continue¶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| public class withContinue {
public static void main(String[] args) {
System.out.println(catchContinue());
}
private static String catchContinue() {
for (int i = 0; i < 2; i++) {
try {
System.out.println("try block");
throw new Exception("throwing exception");
} catch (Exception e) {
System.out.printf("catch the exception: `%s` in catch block\n", e.toString());
continue;
} finally {
System.out.println("finally block");
}
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
1
2
3
4
5
6
7
| try block
catch the exception: `java.lang.Exception: throwing exception` in catch block
finally block
try block
catch the exception: `java.lang.Exception: throwing exception` in catch block
finally block
outside the try-catch-finally block
|
可见,仍然会继续运行 finally 块中的代码再进行下次循环。
finally 中有 continue¶
在 catch 块中抛出异常,观察 finally 中 continue 的运行现象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| public class withContinue {
public static void main(String[] args) throws Exception {
System.out.println(finallyContinue());
}
private static String finallyContinue() throws Exception {
for (int i = 0; i < 2; i++) {
try {
System.out.println("try block");
throw new Exception("throwing exception");
} catch (Exception e) {
System.out.println("catch block, throwing exception");
throw new Exception("throwing exception");
} finally {
System.out.println("finally block");
continue;
}
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
1
2
3
4
5
6
7
| try block
catch block, throwing exception
finally block
try block
catch block, throwing exception
finally block
outside the try-catch-finally block
|
主线程并不会捕获到异常,因为 finally 中的 continue 导致 catch 中的异常无法被抛出。
try, catch, finally 中有 break¶
try 中有 break¶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| public class withBreak {
public static void main(String[] args) throws Exception {
System.out.println(tryBreak());
}
private static String tryBreak() {
for (int i = 0; i < 2; i++) {
try {
System.out.println("try block");
break;
} catch (Exception e) {
System.out.printf("catch the exception: `%s` in catch block\n", e.toString());
} finally {
System.out.println("finally block");
}
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
1
2
3
| try block
finally block
outside the try-catch-finally block
|
当代码运行到 try 的 break 后,执行 finally 块中的逻辑跳出循环。
catch 中有 break¶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| public class withBreak {
public static void main(String[] args) throws Exception {
System.out.println(catchBreak());
}
private static String catchBreak() {
for (int i = 0; i < 2; i++) {
try {
System.out.println("try block");
throw new Exception("throwing exception");
} catch (Exception e) {
System.out.printf("catch the exception: `%s` in catch block\n", e.toString());
break;
} finally {
System.out.println("finally block");
}
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
1
2
3
4
| try block
catch the exception: `java.lang.Exception: throwing exception` in catch block
finally block
outside the try-catch-finally block
|
在 catch 中捕获异常后仍然会继续运行 finally 块中的代码再跳出循环。
finally 中有 break¶
在 catch 块中抛出异常,观察 finally 中 break 的运行现象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| public class withBreak {
public static void main(String[] args) throws Exception {
System.out.println(tryBreak());
}
private static String finallyBreak() throws Exception {
for (int i = 0; i < 2; i++) {
try {
System.out.println("try block");
throw new Exception("throwing exception");
} catch (Exception e) {
System.out.println("catch block, throwing exception");
throw new Exception("throwing exception");
} finally {
System.out.println("finally block");
break;
}
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
1
2
3
4
| try block
catch block, throwing exception
finally block
outside the try-catch-finally block
|
与 finally 中有 continue 的结果类似。主线程并不会捕获到异常,因为 finally 中的 break 导致 catch 中的异常无法被抛出。
try, catch 中有 exit¶
当 try,catch 中有 System.exit() 时,JVM 将被关闭,finally 中的代码将不会被运行。
try 中有 exit¶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| public class withExit {
public static void main(String[] args) {
System.out.println(tryExit());
}
private static String tryExit() {
try {
System.out.println("try block");
System.exit(1);
} catch (Exception e) {
System.out.printf("catch the exception: `%s` in catch block\n", e.toString());
} finally {
System.out.println("finally block");
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
可见,程序直接从 try 块中的 System.exit(1) 退出了,没有执行 finally 块的内容。
catch 中有 exit¶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| public class withExit {
public static void main(String[] args) {
System.out.println(catchExit());
}
private static void throwException() throws Exception {
throw new Exception("throwing Exception");
}
private static String catchExit() {
try {
System.out.println("try block");
throwException();
} catch (Exception e) {
System.out.printf("catch the exception: `%s` in catch block\n", e.toString());
System.exit(1);
} finally {
System.out.println("finally block");
}
return "outside the try-catch-finally block";
}
}
|
运行结果为:
1
2
| try block
catch the exception: `java.lang.Exception: throwing Exception` in catch block
|
程序直接从 catch 块中的 System.exit(1) 退出了,没有执行 finally 块的内容。
守护进程¶
当程序中所有用户线程都终止时,JVM 会终止所有相关守护线程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| public class withThread {
public static void main(String[] args) {
System.out.println(daemonThread());
}
private static String daemonThread() {
Thread thread = new Thread(() -> {
try {
System.out.println("try block");
Thread.sleep(2000);
System.out.println("try end");
} catch (InterruptedException e) {
System.out.println("catch block");
} finally {
System.out.println("finally block");
}
});
thread.setDaemon(true);
thread.start();
return "main thread end";
}
}
|
新建一个守护线程,并在其 try 块中设置一个执行时间很久的任务(这里用 sleep 代替)。主线程将守护进程启动后,即可退出。
运行结果为:
1
2
| main thread end
try block
|
可见其在主线程退出后,守护线程也被终止了。而且值得注意的是,守护线程并没有执行 finally 块,而是直接被 JVM 终止(就如运行 System.exit() )。

本作品采用
知识共享署名-相同方式共享 4.0 国际许可协议进行许可。