异常说明
- java强制让函数名后面接上
throws+异常类型明示这个方法可能抛出的所有异常类型,比如f()中可能在某些判断体内会有TooBig, TooSmall, DivZero这些类型的异常,那么代码在实现的时候,就需要加上
void f() throws TooBig, TooSmall, DivZero{...}
- 只有
RuntimeException类型的异常是可以不显示表示的 - 如果
f()潜在一些异常,但是却没有被告知,那么f()将会被编译器提醒要检查异常 - 可以在异常说明中写上该方法可能不会抛出的异常,这一般出现在派生类和接口的定义中,为的是让继承类不用修改已有的办法
捕获所有异常
catch(Exception e),将绝大多数异常类型的基类Exception写道形参中即可, 这个捕获一般是放到最后来捕获遗漏的异常。Exception继承自Throwable基类,含有方法:
String getMessage():返回详细信息String getLocalizeMessage():返回本地详细信息String toString():返回类型简单描述void printStackTrace():默认输出到System.errvoid printStackTrace(PrintStream): 输出到如System.out输出对象void printStackTrace(java.io.PrintWriter):输出到PrintWriter对象Throwable fillInStackTrace():在对象内部记录栈帧当前状态,用于重新抛出错误,得到接住这个异常的方法不会记录这个异常抛出点之前的异常抛出点getStackTrace(): 返回一个由栈轨迹元素构成的数组,栈顶(数组第一个元素)是最后调用的函数,栈底(数组最开始的元素)是调用序列的第一个函数
异常链
- 捕获一个异常之后,接着抛出另一个异常,希望把原始的异常信息保存下来
Throwable子类构造器可以接受一个cause对象作为参数,该对象用于表示原始的异常。- 只有三个
Throwable的子类拥有带cause的构造器,分别是Exception, RuntimeException和, Error - 想要将所有类型的异常的形成异常链,需要用
initCause()方法而不是构造器
JAVA标准异常
- 两大类:
Error和Exception,一般不用关心Error类型,Exception才是程序员可以主动抛出的 - 除了
java.lang之外,还有util, net, io包中由定义的异常 - 特殊异常
RuntimeException:如NullPointerException,一般而言是JVM中实现的。RuntimeException的捕获可以不屑异常说明,输出会直接发送给System.err,而且RuntimeException可以不用显式写在try块中进行捕获,如果没有捕获,会直达main函数,并且在程序结束前调用printStackTrace()
finally
- 异常捕获三剑客的最后一个模块:无论有没有抛出异常,
finally都会执行 finally的作用:保证try中无论发生了什么,在finally中都能进行对象的释放,不过这个保障对于有GC的语言来说没有那么吸引人。- 对于java而言, 要把除内存之外的资源恢复到初始状态,或者最终想要保持的状态,可以考虑使用
finally finally的作用范围:即便在try中进行了break, continue, return等操作,finally也一定会执行。- finally 导致的异常丢失(JDK 1.5,后续版本不知道会不会这样):唉卡在嵌套
try中,try中的异常被finally中的异常覆盖
class importantException extends Exception{
public String toString(){
return "A very important Exception";
}
}
class HoHumException extends Exception{
public String toString(){
return "A trivial Exception";
}
}
public class LostMessage{
void f() throws importantException {
throw new importantException();
}
void g() throws HoHumException{
throw new HoHumException();
}
public static void main(String[] args){
try{
try{
LostMessage lm = new LostMessage();
try{
lm.f();
}finally{
lm.g();
}
}catch(Excetpion e){
System.out.println(e);
}
}
}
}
异常限制
- 在子类继承基类的时候,只能抛出在基类方法的异常说明里面的样式,这确保了基类代码应用到派生类对象的时候,一样能够工作
异常匹配机制
- 抛出异常之后,异常处理系统会按照书写顺序找到最近的捕获语句,一旦匹配到,处理系统就默认异常已经处理完毕,不再往下寻找。
- 异常匹配机制要求,书写代码的时候,子类异常一定要位于基类异常的前面,不然由于向上转型的原因,会导致子类异常永远无法被捕获。
参考