第十一章 异常处理
异常机制
如果你把有风险的程序代码包含在try/catch块中,那么编译器会放心很多。
try/catch块会告诉编译器你确实已经知道所调用的方法会有风险,并且也已经准备好要处理它,它只会注意你有没有便是你会注意到异常。
try{
//把有风险的程序放在try块
}catch(Excepotion ex){
//catch块摆放异常状况的处理程序,这一段只会在有抛出异常时执行
}
异常是一种Exception类型的对象。因为它是对象,所以你catch住的也是对象。上面的程序代码中catch的参数是Exception类型的ex引用变量。
你写在catch块中的程序必定与所抛出的异常有关。例如,如果遇到服务器出故障的异常,你可能会在这里写寻找替代服务器的方法。
当你的程序代码调用有风险的方法时,也就是声明有异常的方法,就是该方法把异常丢给你的。
实际上,两者可能都是你自己写的。由谁写的程序其实并不重要,重点在于哪个方法抛出异常与哪个方法抓住它。
在编写可能会抛出异常的方法时,它们都必须声明有异常。
1. 有风险、会抛出异常的程序代码:
public void takeRisk()throws BadException{
if(abandonAllHope){
throw new BadException();//创建异常对象并抛出
}
}
2. 调用该方法的程序代码:
public void crossFingers(){
try{
takeRisk();
}catch(BadException ex){
ex.printStackTrace();//如果无法从异常中恢复,至少也要使用printStackTrace()来列出有用的信息
}
}
方法可以抓住其他方法所抛出的异常。异常总是会丢回给调用方。会抛出异常的方法必须要声明它有可能会这么做。
Exception中有一个特殊的子类异常:RuntimeException(运行时异常)。如果在函数上声明了该异常,调用者可以不用进行处理。编译一样通过,之所以不用在函数进行声明,是因为不需要让调用者进行处理,当该异常发生,希望程序停止,因为在运行时出现了无法继续运算的情况,希望停止程序后对代码进行修正
try/catch流程控制
try{
Foo f = x.doRiskyThing();
int b = f.getNum();
}catch(Exception ex){
System.out.println("failed");
}
System.out.println("We made it");
如果成功的话,执行完try块中的内容后就不会执行catch块中的内容,会跳过catch块直接运行下面的代码。
Foo f = x.doRiskyThing();
这行出现了异常,那么就不会执行
int b = f.getNum();
try中剩下的代码,直接执行catch块中的代码。
finally:无论如何都要执行的部分
finally是用来存放不管有没有异常发生都得执行的程序(通常用来关闭连接)。
对多异常的处理
异常在子父类覆盖中的体现
throw和throws的区别
不需要处理异常的时候,可以在方法上将接受到的异常继续抛出。