阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

捕获异常

29次阅读
没有评论

共计 2722 个字符,预计需要花费 7 分钟才能阅读完成。

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

多 catch 语句

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

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

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的顺序非常重要:子类必须写在前面。例如:

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) {...} 捕获并执行。

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

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 再写一遍。例如:

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语句块保证有无错误都会执行。上述代码可以改写如下:

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 有几个特点:

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

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

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

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

void process(String file) throws IOException {try {...} finally {System.out.println("END");
    }
}

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

捕获多种异常

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

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的代码是相同的,所以我们可以把它两用 | 合并到一起:

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 捕获异常并处理。

下载练习

小结

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

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

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

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-08-05发表,共计2722字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中