如何优雅的处理异常

2019-02-28  本文已影响0人  打不过猫的鱼

1.异常的定义

在《java编程思想》中这样定义异常:阻止当前方法或作用域继续执行的问题。

2.异常的体系


在Java中异常被当做对象来处理,根类是java.lang.Throwable类,所有异常类都必须直接或间接继承自Throwable类,Throwable类分为以下两个子类:

3.如何抛异常

Use checked exceptions for recoverable conditions and runtime exceptions for programming errors
——Effective Java Item 58

    public FileInputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null);
    }

    public FileInputStream(File file) throws FileNotFoundException {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(name);
        }
        if (name == null) {
          // name is null 不是必然发生的,具有偶然性,抛出非受检性异常
            throw new NullPointerException();
        }
        if (file.isInvalid()) {
            // file不存在,不知道如何处理,程序无法继续,抛出受检性异常,希望调用方来处理
            throw new FileNotFoundException("Invalid file path");
        }
        fd = new FileDescriptor();
        fd.attach(this);
        path = name;
        open(name);
    }

4.如何有效的使用异常

判断是否有效的使用异常,要看是否能够回答以下问题:

如果你的异常没有回答以上全部问题,那么可能你没有很好地使用它们。在有效使用异常的情况下:

4.1三原则

有三个原则可以帮助你最大限度地使用好异常,这三个原则是:

4.1.1具体明确

4.1.2提早抛出

4.1.3延迟捕获

  /**
  * bad case
  */
  public void read(String filename){
      InputStream in = null;
      try{
          in = new FileInputStream(filename);
      } catch (FileNotFoundException e){
          logger.error(e);
          //throw e;
      }
      in.read(...);
}
  /**
  * good case
  */
  public void read(String filename) throws IllegalArgumentException, FileNotFoundException{
       if (filename == null){
           throw new IllegalArgumentException("filename is null");
       }
       InputStream in = new FileInputStream(filename);
       in.read(...);
  }

5.异常的设计和处理建议

5.1只在必要使用异常的地方才使用异常,不要用异常去控制程序的流程

5.2避免多次在日志信息中记录同一个异常

5.3异常处理尽量放在高层进行

5.4对可恢复的情况使用受检异常,对编程错误使用运行时异常

5.5避免不必须要的使用受检异常

5.6抛出与抽象相对应的异常

public E get(int index) {
    try {
        return listIterator(index).next();
    } catch (NoSuchElementException exc) {
        throw new IndexOutOfBoundsException("Index: "+index);
    }
}
  try{
    //...to something
  }catch(LowerLevelException cause){
    //这里抛出高层的异常中会带有低层异常的信息
    throw new HighLevelException(cause)
  }

5.7在细节消息中包含能捕获的失败信息

    private static Object add(Object array, int index, Object element, Class clss) {
        if (array == null) {
            if (index != 0) {
                throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
            }
            Object joinedArray = Array.newInstance(clss, 1);

            Array.set(joinedArray, 0, element);
            return joinedArray;
        }
        int length = Array.getLength(array);
        if (index > length || index < 0) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
        }
        Object result = Array.newInstance(clss, length + 1);
        System.arraycopy(array, 0, result, 0, index);
        Array.set(result, index, element);
        if (index < length) {
            System.arraycopy(array, index, result, index + 1, length - index);
        }
        return result;
    }

5.8努力使失败保持原子性

default void sort(Comparator<? super E> c) {
    Object[] a = this.toArray();
    Arrays.sort(a, (Comparator) c);
    ListIterator<E> i = this.listIterator();
    for (Object e : a) {
      i.next();
      i.set((E) e);
    }
}

传送门:阿里的异常使用规范

上一篇 下一篇

猜你喜欢

热点阅读