搜索 K
Appearance
博客正在加载中...
Appearance
异常处理模型基于三种操作:声明一个异常(declaring an exception)、抛出一个异常 (throwing an exception)和捕获一个异常(catching an exception)。
我们来简单说明下上述三种操作
method2() throws Exception{
if (an error occurs){
throw new Exception();
}
}在 method2 的方法头里,声明了它可能抛出的必检异常的类型,这里简单写了 Exception,具体情况具体分析,如果是操作 IO,那么应该抛出 IOException。
在第 3 行抛出了一个异常。
在 method1 里用了 try-catch 块来捕获异常:
method1(){
try{
method2();
}catch(Exception ex){
process exception;
}
}在 Java 中,当前执行的语句必属于某个方法。一个程序从 main 方法开始执行一个程序。每个方法都必须声明它可能抛出的必检异常的类型,这称为声明异常( declaring exception)。
由于任何代码都可能发生免检异常,因此无需在方法里显示声明;但必检异常必须在方法头中显式声明,这样,方法的调用者会被告知有异常。
为了在方法中声明一个异常,就要在方法头中使用关键字 throws:
public void myMethod() throws IOException关键字 throws 表明 myMethod 方法可能会抛出异常 IOException。如果方法可能会抛出多个异常,就可以在关键字 throws 后添加一个用逗号分隔的异常列表:
public void myMethod() throws Exceptionl, Exception2, …, ExceptionN注意:如果方法没有在父类中声明异常,那么就不能在子类中对其进行继承来声明异常,例如下述代码:
public class LearnExceptionDemo1 {
public static void main(String[] args) {
try {
new Student().run();
} catch (Exception e) {
}
}
}
class Person{
void run(){
System.out.println("person run!");
}
}
class Student extends Person{
@Override
void run() throws Exception {
System.out.println("student run!");
}
}编译会报错:
$ javac LearnExceptionDemo1.java
LearnExceptionDemo1.java:22: 错误: Student中的run()无法覆盖Person中的run()
void run() throws Exception {
^
被覆盖的方法未抛出Exception
1 个错误检测到错误的程序可以创建一个合适的异常类型的实例并抛出它,这就称为抛出一个异常(throwing an exception)。
例如,假如程序发现传递给方法的参数与方法的合约不符(例如,方法中的参数必须是非负的,但是传入的是一个负参数),这个程序就可以创建 IllegalArgumentException 的一个实例:
IllegalArgumentException ex = new II1egalArgumentException("Wrong Argument");tips:Java 中每个异常类至少有两个构造方法:一个无参构造方法和一个带有描述这个异常的 String 参数的构造方法。该参数称为异常消息(exception message),它可以用
getMessage()获取。
然后可以抛出(throw)该异常:
throw ex;或者简化为一条语句:
throw new IllegalArgumentException ("Wrong Argument");当抛出一个异常时,可以在 try-catch 代码块中捕获和处理它,格式如下:
try {
statements; // Statements that may throw exceptions
}
catch (Exception1 exVarl){
handler for exceptionl;
}
catch (Exception2 exVar2){
handler for exception2;
}
...
catch (ExceptionN exVarN){
handler for except!onN;
}首先,我们将可能发生异常的代码,用 try 块包住,然后会发生两种情况:一种是发生了异常,另一种没有发生。我们来分别看看两种情景,try-catch 代码块的处理逻辑
我们运行代码,如果发生了异常,则:
IOExcetion,NullPointerException,每个 catch 块可以称为一个异常处理器(exception handler)。catch 语句只有一个能被执行假设 main 方法调用 method1, method1 调用 method2,method2 调用 methods3, method3 抛出一个异常,如图 所示。

我们分几种情况来看,异常的捕获是怎么样的:
如果在执行 try 块的过程中没有出现异常,则跳过 catch 子句,也就是继续执行 try-catch 块之后的代码。
RuntimeException是 Exception的子类,必须先捕获 RuntimeException,再捕获 Exception。这很好理解,如果父类现在前面,那么子类的异常是永远捕获不到的Java7 版本出了一个新特性,可以在一个 catch 块中捕获多种类型的异常:每个异常类型使用竖线( | )与下一个分隔。如果其中一个异常被捕获,则执行处理的代码。
catch (Exceptionl | Exception2 | … | Exceptionk ex){
}这样消除了重复的代码,例如下面的例子中,每个 catch 块都有重复的代码:
catch (IOException ex) {
logger.log(ex);
throw ex;
catch (SQLException ex) {
logger.log(ex);
throw ex;
}可以简写为:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}注意:
异常处理模型基于三种操作:声明一个异常、抛出一个异常和捕获一个异常
声明异常的关楗字是 throws, 抛出异常的关键字是 throw。
异常的处理器是通过从当前的方法开始,沿着方法调用链,按照异常的反向传播方向找到的。