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

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) } } } 

从我研究的“e”应该是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 

? 谢谢。

当你使用multi-catch子句catchException1 | Exception2 eforms)时, Exception1 | Exception2 e的编译时类型是两种类型共有的最大类型,因为代码当然必须处理任何一种类型的exception从规格 :

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

将其例外参数表示为单个类类型的catch子句称为uni-catch子句

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

声明的exception参数类型,表示其类型为与备用D1 | D2 | ... | Dn D1 | D2 | ... | Dn D1 | D2 | ... | Dnlub(D1, D2, ..., Dn)

…这里定义的lub是最小上界。

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

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

如果Exception1Exception2上都存在info ,则重构它们以便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 } 

…所以编译器可以给出类型TheAncestorException并使info可访问。

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

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

这里e是Exception1和Exception2的引用变量。 所以在编译时e.info(); 将抛出exception,因为对于Exception2 info()不存在。

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

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