1 try-catch-finally
调用栈 call stack 可以使用throw抛出任何异常和自定义异常,抛出之后程序方法不在往下执行; 当异常发生时,如果在try-catch块中,就执行catch中的方法逻辑; 如果try-catch中有return方法,finally将在return之前执行完成;
2 异常定义
异常总类定义,和具体异常子类定义,有利于更细地处理异常; 异常包装wrapping 让异常包装成一般异常,统一,这样在方法调用时, 子方法抛出具体的异常信息,方法调用子方法时,可以声明一个统一的异常
为什么包装异常,如何包装异常
- 如果不同方法声明抛出不同异常,上层方法需要声明抛出所有异常,会比较混乱
- 上层方法调用下层方法时,不会关心具体异常该怎么处理
3 检查异常和非检查异常
-
非检查异常不需要捕获或声明抛出异常,非检查异常继承了java.lang.RuntimeException
-
检查异常继承了 java.lang.Exception,Checked Exception 让开发者记得去处理异常
4 选择是checked Exception or unchecked Exceptions?
不要混用这两种异常,否则会造成混乱,后来建议使用unchecked Exceptions这样减少了try-catch的使用和声明式异常使用
5 失败安全异常处理
eg non-fail-safe FileInputStream 抛出异常第一个catch捕获 执行finally时,input为null,抛出空异常,最后会覆盖了之前异常,方法抛出空指针异常
try{
input = new FileInputStream("myFile.txt");
//do something with the stream
} catch(IOException e){
throw new WrapperException(e);
} finally {
try{
input.close();
} catch(IOException e){
throw new WrapperException(e);
}
} ```
6 可插拔的自定义异常处理器
public interface ExceptionHandler {
public void handle(Exception e, String errorMessage);
}
使用异常处理的类
protected ExceptionHandler exceptionHandler = null;
public void setExceptionHandler(ExceptionHandler handler){
this.exceptionHandler = handler;
}
public void processFile(String fileName){
FileInputStream input = null;
try{
input = new FileInputStream(fileName);
processStream(input);
} catch (IOException e){
this.exceptionHandler.handle(e,
"error processing file: " + fileName);
}
}
protected void processStream(InputStream input)
throws IOException{
//do something with the stream.
}
}
定义异常处理实现类,可以通过组件本身要做的事情去决定handle方法的入参个数和类型
可以有一个默认地异常处理器,来处理异常
public class IgnoringHandler implements ExceptionHandler{
public void handle(Exception e, String message) {
//do nothing, just ignore the exception
}
}
public class WrappingHandler implements ExceptionHandler{
public void handle(Exception e, String message){
throw new RuntimeException(message, e);
}
}
public class CollectingHandler implements ExceptionHandler{
List exceptions = new ArrayList();
public List getExceptions(){ return this.exceptions; }
public void handle(Exception e, String message){
this.exceptions.add(e);
//message is ignored here, but could have been
//collected too.
}
}
7 在什么地方用日志记录异常
A B ... F 这个表示调用关系,A处于top,B处于mid, F处于buttom 在底层记录异常日志,可以在异常发生的地方立即记录日志
- 这样需要在每一个组件异常地方记录日志,这是一个比较费力的事情
- 组件之间并不知道异常各自是如何记录的
- 如果组件内部记录的日志信息不够全面,那么就没有足够的日志信息去写详细的日志
在中间层记录异常
- 日志不够全面,底层需要补充更多详细日志信息和错误码信息,这样才能全面统计日志
- 有很多相似代码在中间层记录日志信息,如果日志策略变化之后,很多地方需要修改
也许可以通过切面植入日志,但这里不考虑
在上层记录日志,有一个统一的地方捕获异常并记录
- 一个地方维护日志,方便维护
- 缺点,并不知道是底层哪些地方的错误异常
7 如何丰富异常信息
将原异常进行捕获,然后在catch中补充异常信息,丰富异常 。重新抛出异常,这样不会影响异常栈i信息记录轨迹
8 校验器,趁早抛出异常
把所有的校验都提前,放到后续操作之前,防止信息一半校验通过使用了,一半校验失败
9
来源:oschina
链接:https://my.oschina.net/iioschina/blog/4298679