2

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

? 谢谢。

4

3 回答 3

4

当您使用多捕获子句(的Exception1 | Exception2 e形式catch)时,编译时类型e是两种类型共有的最大类型,因为代码当然必须处理任何一种类型的异常。来自规范

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

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

将异常参数表示为类型联合的 catch 子句称为multi-catch 子句

...

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

...这里定义lub的最小上限在哪里。

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

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

如果info两者都存在Exception1,则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可访问。

于 2017-11-14T09:51:54.973 回答
1

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

于 2017-11-14T09:53:42.123 回答
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);
        }
于 2017-11-14T09:53:09.970 回答