java异常处理

南笙酒味 提交于 2020-08-18 13:39:17

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!