1 异常
1.1 基类
java中,异常对象都派生自Throwable。
1.2 分类
继承自Throwable的子类分为两类:Error和Exception。
1.2.1 Error
Error分支代表java运行时系统内部错误和资源耗尽错误,应用程序不该抛出此类对象。如果运行时出现此种错误,除通知用户外,无处理方法。
1.2.2 Exception
设计java程序时需要关注该分支。该分支又分为两类:继承自RuntimeException的异常及其他异常(如IOException)。
划分原则是:由程序本身逻辑错误导致的异常为RuntimeException;程序本身逻辑没问题,但由诸如I/O错误等这类因为应用运行环境等导致的异常属于其他异常。
1.2.2.1 RuntimeException
该类异常包含:ArrayIndexOutOfBoundsException、NullPointerException、ClassCastException等。
”如果出现RuntimeException,则一定是你的问题“。
1.2.2.2 其他异常
I/O错误,试图根据字符串查找不存在的Class对象等。
1.3 未检查异常和检查异常
java语言规范将Error类和RuntimeException类的所有异常称为未检查异常;将其他所有异常称为已检查异常。
编译器会检查是否已为声明会抛出的所有已检查异常提供了异常处理或是否已将其继续传递。
如果在一个方法中调用了另一个声明了可能抛出异常的方法,则当知道如何处理所声明的异常时,就该捕获这些异常并处理;如果不知道如何处理,则应该继续传递这些异常,即,在方法首部添加throws,声明可能抛出这些异常。
2 异常处理
方法必须声明所有可能抛出的已检查异常,而不应该声明未检查异常。
因为未检查异常要不在我们控制范围之外(如Error),要不是应该避免的,即我们应该花时间在程序中修改这些错误而非说明这些错误发生的可能(如NullPointerException)。
2.1 子类对异常的处理
1、如果子类覆盖超类的方法,则子类的该方法所声明的已检查异常要么比超类该方法所声明的异常更具体(即,子类继续传递该类型的异常),要么不声明任何异常(即,子类自行处理这些异常)。
如果超类的方法没有声明抛出任何已检查异常,则子类覆盖该方法时,也不能声明抛出任何已检查异常。
2.2 捕获多个异常
如果对几类异常的处理一致,则可以在一个catch子句同时捕获这几类异常,如:
try{
...
}
catch(FileNotFoundException | UnknownHostException ex){ //此时ex隐含为final变量
....
}
catch(IOException ex){
...
}
2.3 包装异常
如果方法中发生了已检查异常,但又不允许抛出此类异常,我们可捕获该异常后将其包装为一个RuntimeException,如:
Throwable unCheckedEx = new RuntimeExceptionXx("xx")
unCheckedEx.initCause(checkedEx);
throw unCheckedEx;
可使用unCheckedEx.getCause()获取该异常。
2.4 重新抛出异常
可以在catch子句中重新抛出异常,以改变抛出异常的类型,隐藏某些系统细节。
2.5 独立使用try/catch 和 try/finally子句提高可读性
try{
try{
...
}
finally //也可能发生异常,若发生可由外层catch子句捕获
....
}
}
catch(Exception ex){
....
}
方法返回前会执行finally子句,如果finally子句中也有return语句,则这个返回值会覆盖原始返回值。注:以上内容引自<java核心技术>一书