Java使用try-catch捕获异常
示例
可以使用该try...catch语句捕获和处理异常。(实际上,try语句采用其他形式,如关于try...catch...finally和的其他示例所述try-with-resources。)
尝试捕获一个捕获块
最简单的形式如下:
try { doSomething(); } catch (SomeException e) { handle(e); } //下一个陈述
一个简单的行为try...catch如下:
try执行块中的语句。
如果该try块中的语句未引发任何异常,则控制传递到之后的下一个语句try...catch。
如果在该try块内引发异常。
该变量e绑定到异常对象。
catch执行该块中的代码。
如果该代码引发异常,那么将传播新引发的异常以代替原始异常。
否则,控制权传递到try...catch。之后的下一条语句。
测试异常对象以查看其是实例SomeException还是子类型。
如果是,则该catch块将捕获异常:
如果不是,则原始异常继续传播。
尝试捕获与多个捕获
一个try...catch也可以有多个catch块。例如:
try { doSomething(); } catch (SomeException e) { handleOneWay(e) } catch (SomeOtherException e) { handleAnotherWay(e); } //下一个陈述
如果有多个catch块,则从第一个块开始一次尝试一次,直到找到匹配的例外。执行相应的处理程序(如上所述),然后将控制权传递给该语句之后的下一个try...catch语句。即使处理程序代码抛出异常catch,也始终会跳过与之匹配的块之后的块。
“自上而下”的匹配策略会对catch块中的异常没有脱节的情况产生影响。例如:
try { throw new RuntimeException("test"); } catch (Exception e) { System.out.println("Exception"); } catch (RuntimeException e) { System.out.println("RuntimeException"); }
此代码段将输出“Exception”,而不是“RuntimeException”。由于RuntimeException是的子类型Exception,因此第一个(更一般)catch会被匹配。第二个(更具体的)catch将永远不会执行。
从中学到的教训是,最具体的catch块(就异常类型而言)应该首先出现,而最一般的块应该位于最后。(如果acatch永远无法执行,则某些Java编译器会警告您,但这不是编译错误。)
多例外捕获块
从JavaSE7开始,单个catch块可以处理一系列不相关的异常。列出了例外类型,并用竖线(|)符号分隔。例如:
try { doSomething(); } catch (SomeException | SomeOtherException e) { handleSomeException(e); }
多异常捕获的行为是单异常情况的简单扩展。本catch场比赛,如果抛出的异常匹配(至少)列出的例外之一。
规范中还有一些其他细微之处。的类型e是列表中异常类型的综合联合。使用的值时e,其静态类型是类型并集的最不常见的超类型。但是,如果e在catch块内重新抛出,则抛出的异常类型是联合中的类型。例如:
public void method() throws IOException, SQLException try { doSomething(); } catch (IOException | SQLException e) { report(e); throw e; }
在上述IOException和SQLException中,检查了最不常见的超类型为的异常Exception。这意味着该report方法必须匹配report(Exception)。但是,编译器知道throw只能抛出IOException或SQLException。因此,method可以声明为throwsIOException,SQLException而不是throwsException。(这是一件好事:请参阅陷阱-ThrowingThrowable,Exception,Error或RuntimeException。)