目录
2.1 checked and unchecked exceptions
2.2 判断使用checked exceptions or unchecked exceptions?
1 前言
Java中有两种“Abnormals”——Error和Exception:
Error:描述java中的内部系统错误和java运行系统资源耗尽的情况。面对此种情况,程序员通常无能为力,只能想办法让程序优雅地结束。(例:VirtualMachineError,LinkageError)
Exception(异常):描述你自己程序导致的问题,可以捕获和处理。(例:FileNotFoundException,IOException)
面对Error我们无能为力,因此本文我们就主要关注我们能处理的Exception。
2 异常
2.1 checked and unchecked exceptions
checked exceptions: 必须捕获并指定错误处理handler,否则编译无法通过,类似于编程语言中的static type checking。
unchecked exceptions: 可以不处理,编译不会出现问题,但执行时出现就导致程序失败(代表程序中的潜在bug),类似于编程语言中的dynamic type checking。
2.2 判断使用checked exceptions or unchecked exceptions?
准则:
1.如果客户端可以通过其他方法恢复异常,则采用checked exceptions
2.如果客户端对出现的这种异常无能为力,则采用unchecked exceptions
3.不要创建无意义的异常,客户应该从checked exception中获取更有价值的信息,利用异常返回的信息来明确操作失败的原因 ; 如果客户仅仅想看到异常信息,可以简单抛出一个unchecked exception
2.3 checked exceptions的处理操作
处理操作中的五个关键词:
throws: 声明本方法中可能会发生某某异常
throw: 抛出某某异常
try, catch, finally: 捕获并处理某某异常
2.3.1 throws
一个java方法遇到无法处理的异常时,会throws这个异常,让调用这个方法的client进行异常进行处理。所以,我们的方法会throws那些异常呢?
1. 其他函数传来的异常:从所调用的函数抛出的checked exceptions
2. 本函数中的异常:当前方法检测到错误并使用throws抛出一个checked exception
考虑到子类型的异常抛出,值得注意的一点是(LSP原则):
1. 如果父类型的方法未抛出异常,则子类型的方法也不能排出异常
2. 子类型方法可以抛出更具体的异常,但抛出异常类型一定不能比父类型抛出的异常类型更宽泛
2.3.2 如何抛出一个异常
1. 找到一个可表达错误的Exception类或者构造一个新的Exception类
2. 构造Exception类的实例,将错误信息写入
3. 抛出它(一旦抛出异常,方法不会在将控制权返回给调用它的client,因此也无需考虑返回错误代码)
若此时JDK提供的exception类无法充分描述你的程序发生的错误,可以创建自己的异常类(直接继承Exception类或者Exception的子类)。
例如此时我们构造一个java.lang.Exception的子类:
public class FooException extends Exception{
public FooException() {super();}
public FooException(String message) { super(message); }
public FooException(String message, Throwable cause) {
super(message, cause);
}
public FooException(Throwable cause) { super(cause); }
}
public void calculate(int i) throws FooException, IOException;
同时调用这个方法的方法必须要么处理这个异常要么继续抛出这个异常(or both)
try{
...
} catch(FooException ex) {
ex.printStackTrace();
System.exit(1);
} catch(IOException ex) {
throw new FooException(ex);
}
2.3.3 try-catch-finally
简单的说,try-catch机制负责捕获异常,而finally负责清理异常发生前申请的资源(因为异常抛出后,方法正常执行的代码或被终止)。
下面是三种情况中try-catch-finally的运行机制:
case 1:程序中未抛出异常
case 2: 程序抛出一个异常并被catch捕获
case 3:程序抛出异常但并未被程序中的catch捕获(最后finally执行完会返回到client)
同时,这里还有个特殊情况:程序中只使用try-finally。在这种情况中finally中的代码都会被执行,无论try中的是否遇到一个异常,如果遇到一个异常,则会被抛出且必须在别的catch中被捕获。