多捕获块中的引用类型的异常问题

时间:2017-11-14 09:45:21

标签: java exception exception-handling multi-catch

e的类型为Exception,但在下面的代码中输出Exception1:

class Exception1 extends IOException {void info(){}}
class Exception2 extends Exception {}

class TestMultiCatch {
    public static void main(String args[]) {
        try {
            int a = 10;
            if (a <= 10)
                throw new Exception1();
            else
                throw new Exception2(); 
        } catch (Exception1 | Exception2 e) {
            e.info();  //line 1 error "The method info() is undefined for type Exception"
            System.out.println(e);   //prints Exception1 (after commenting line 1)
        }
    }
}

从我学习的东西&#34; e&#34;应该是Exception类型,它是Exception1和Exception2的公共基类。从第1行的消息可以看出它是什么。

但是为什么:

System.out.println(e); //prints Exception1 and not Exception
System.out.println(e instanceof IOException); //prints true and not false
System.out.println(e instanceof Exception1); //prints true and not false
System.out.println(e instanceof Exception2); //false

? 感谢。

3 个答案:

答案 0 :(得分:4)

当您使用 multi-catch子句Exception1 | Exception2 e形式的catch)时,编译时类型e是最好的类型这两种类型有一个共同点,因为代码当然必须处理任何类型的异常。从the spec

  

异常参数可以将其类型表示为单个类类型或两个或更多类类型的联合(称为替代)。联合的替代方法在语法上由|分隔。

     

其异常参数表示为单个类类型的catch子句称为 uni-catch子句

     

一个catch子句,其exception参数表示为类型的并集,称为 multi-catch子句

     

...

     

声明类型的异常参数,表示其类型为与替代D1 | D2 | ... | Dn的联合,为lub(D1, D2, ..., Dn)

...其中lub是定义为here的最小上界。

如果您想使用特定于Exception1Exception2的任何内容,请使用单独的catch块:

} catch (Exception1 e) {
    // Something using features of Exception1
} catch (Exception2 e) {
    // Something using features of Exception2
}

如果infoException1都存在Exception2,请重构它们,以便info存在于它们的共同祖先类中:

class TheAncestorException extends Exception {
    public void info() { // Or possibly make it abstract
        // ...
    }
}
class Exception1 extends TheAncestorException {
    // Optionally override `info` here
}
class Exception2 extends TheAncestorException {
    // Optionally override `info` here
}

...所以编译器可以e类型TheAncestorException并使info可以访问。

答案 1 :(得分:1)

多次捕获似乎是你的问题。您(编译器)只能访问在共同祖先上定义的方法。当然,&#34; e&#34;在运行时期间将是Exception1,但编译器不能假设它,因为它也可能是Exception2。最好为Exception1和Exception2创建一个catch块。

答案 2 :(得分:0)

catch (Exception1 | Exception2 e) {....}

这里e是Exception1和Exception2的引用变量。因此,在编译时e.info();将抛出异常,因为info()不存在Exception2

最好为每个类使用单独的catch块,因为这两个类没有相同的方法info()

} catch (Exception1 e) {
            e.info();  
            System.out.println(e);  
        } catch (Exception2 e) {
            System.out.println(e);
        }