第六十一条 抛出与抽象相对应的异常

异常,也有一套自己的体系,尤其是java的一大特征是封装,所以对应的,如果封装的方法中抛出的异常与它执行的任务没什么明显的关系,则很容易令人不知所措,给人以驴唇不对马嘴,尤其是方法是由底层抽象方法抛出的异常,更容易发生这种情况,不但编码规范错误,更可能污染高层的api,这样就可能破坏客户端的架构,为了避免这个问题,更高层的实现应该捕获底层的异常,同时向上抛出可以让更高层抽象解释的异常,这种做法叫做异常转译,异常体系架构就是以此为基础产生的。

单个的异常

    try {
            //use low-levelabstraction to do our bidding
        } catch (LowerLevelException e) {
            throw new HigherLevelException();
        }
        
来自AbstractSequentialList类,抽象类,里面有get()方法,它是属于基类的方法,需要子类去实现,也可以说是底层方法,需要上层去实现对应的方法功能,它本身是实现了List<E>接口,按照List中get()方法的规范,异常是必须转译的。

    public E get(int index) {
        try {
            return listIterator(index).next();
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }

get()方法中调用了迭代器的listIterator(index).next() 方法,我们就要预防对应的错误,此时listIterator(int index)方法,注释说的很明白,@throws IndexOutOfBoundsException{@inheritDoc},意思是可能产生越界,所以,AbstractSequentialList的get()就要做好对应的预防,加try或继续往上层抛异常,这里选择的是用try来防止异常的破坏。

异常链是另外一种异常体系,比如底层的异常想抛给高层,一种是刚才的方式,另外一种是如果这两个地方的异常不属于一个体系,怎么办?这种场景就适合异常链。


class Exception1 extends Exception{

}

class Exception2 extends Exception{
    Exception2(Throwable throwable){
        super(throwable);
    }
    Exception2(){
        super();
    }
}

class Test{
    public static void main(String[] args) {
        try {
            a();
        } catch (Exception2 e) {
            e.printStackTrace();
        }
    }

    public static void a() throws Exception2{
        try {
            b();
        } catch (Exception1 e) {
            e.printStackTrace();
            throw new Exception2();
        }
    }
    public static void b() throws Exception1{
        throw new Exception1();
    }
}

如果运行,我们最多只能捕获Exception2的信息,Exception1的信息,我们是不知道的,那么,怎么才能也知道Exception1的呢?我们只需要修改a()方法中的一行代码

    public static void a() throws Exception2{
        try {
            b();
        } catch (Exception1 e) {
            e.printStackTrace();
            throw new Exception2(e); // 这里原先是无参构造,现在是有参构造
        }
    }

大多数的标准异常都支持异常链的构造器,但异常也不能被乱用,应该优先根据条件方法,检查参数的有效性,去绕开一些问题,无法绕开的,再使用异常。

猜你喜欢

转载自blog.csdn.net/Deaht_Huimie/article/details/84032984