【Java】异常处理 之 捕获异常

在Java中,凡是可能抛出异常的语句,都可以用try ... catch捕获。把可能发生异常的语句放在try { ... }中,然后使用catch捕获对应的Exception及其子类。

多 catch 语句

可以使用多个 catch语句,每个catch分别捕获对应的Exception及其子类。JVM 在捕获到异常后,会从上到下匹配catch语句,匹配到某个catch后,执行catch代码块,然后不再继续匹配。

简单地说就是:多个catch语句只有一个能被执行。例如:

java 复制代码
public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException e) {
        System.out.println(e);
    } catch (NumberFormatException e) {
        System.out.println(e);
    }
}

存在多个 catch的时候,catch的顺序非常重要:子类必须写在前面。例如:

java 复制代码
public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException e) {
        System.out.println("IO error");
    } catch (UnsupportedEncodingException e) { // 永远捕获不到
        System.out.println("Bad encoding");
    }
}

对于上面的代码,UnsupportedEncodingException异常是永远捕获不到的,因为它是IOException的子类。当抛出UnsupportedEncodingException异常时,会被catch (IOException e) { ... }捕获并执行。

因此,正确的写法是把子类放到前面:

java 复制代码
public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (UnsupportedEncodingException e) {
        System.out.println("Bad encoding");
    } catch (IOException e) {
        System.out.println("IO error");
    }
}

finally语句

无论是否有异常发生,如果我们都希望执行一些语句,例如清理工作,怎么写?

可以把执行语句写若干遍:正常执行的放到try中,每个catch再写一遍。例如:

java 复制代码
public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
        System.out.println("END");
    } catch (UnsupportedEncodingException e) {
        System.out.println("Bad encoding");
        System.out.println("END");
    } catch (IOException e) {
        System.out.println("IO error");
        System.out.println("END");
    }
}

上述代码无论是否发生异常,都会执行System.out.println("END");这条语句。

那么如何消除这些重复的代码?Java的try ... catch机制还提供了finally语句,finally语句块保证有无错误都会执行。上述代码可以改写如下:

java 复制代码
public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (UnsupportedEncodingException e) {
        System.out.println("Bad encoding");
    } catch (IOException e) {
        System.out.println("IO error");
    } finally {
        System.out.println("END");
    }
}

注意 finally有几个特点:

finally语句不是必须的,可写可不写;
finally总是最后执行。

如果没有发生异常,就正常执行try { ... }语句块,然后执行finally。如果发生了异常,就中断执行try { ... }语句块,然后跳转执行匹配的catch语句块,最后执行finally

可见,finally是用来保证一些代码必须执行的。

某些情况下,可以没有catch,只使用try ... finally结构。例如:

java 复制代码
void process(String file) throws IOException {
    try {
        ...
    } finally {
        System.out.println("END");
    }
}

因为方法声明了可能抛出的异常,所以可以不写catch

捕获多种异常

如果某些异常的处理逻辑相同,但是异常本身不存在继承关系,那么就得编写多条catch子句:

java 复制代码
public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException e) {
        System.out.println("Bad input");
    } catch (NumberFormatException e) {
        System.out.println("Bad input");
    } catch (Exception e) {
        System.out.println("Unknown error");
    }
}

因为处理IOExceptionNumberFormatException的代码是相同的,所以我们可以把它两用|合并到一起:

java 复制代码
public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException | NumberFormatException e) { // IOException或NumberFormatException
        System.out.println("Bad input");
    } catch (Exception e) {
        System.out.println("Unknown error");
    }
}

小结

使用try ... catch ... finally时:

多个catch语句的匹配顺序非常重要,子类必须放在前面;

finally语句保证了有无异常都会执行,它是可选的;

一个catch语句也可以匹配多个非继承关系的异常。

相关推荐
Bruce_Liuxiaowei29 分钟前
基于Python+Flask的MCP SDK响应式文档展示系统设计与实现
开发语言·python·flask·mcp
界面开发小八哥31 分钟前
Java开发工具IntelliJ IDEA v2025.1——全面支持Java 24、整合AI
java·ide·人工智能·intellij-idea·idea
chuxinweihui37 分钟前
数据结构——栈与队列
c语言·开发语言·数据结构·学习·算法·链表
我不是程序猿儿37 分钟前
[C#]反射的实战应用,实际数据模拟
开发语言·c#
wt_cs1 小时前
身份证实名认证接口数字时代的信任基石-node.js实名认证集成
开发语言·node.js·php
普兰店拉马努金1 小时前
【高中数学/古典概率】4红2黑六选二,求取出两次都是红球的概率
java·概率
智商低情商凑1 小时前
CAS(Compare And Swap)
java·jvm·面试
yangmf20401 小时前
使用 Logstash 迁移 MongoDB 数据到 Easysearch
java·elasticsearch·搜索引擎
爱编程的鱼1 小时前
C# 结构(Struct)
开发语言·人工智能·算法·c#
Tiger_shl1 小时前
【Python语言基础】24、并发编程
java·数据库·python