捕获Java-8中的多个异常

捕获Java-8中的多个异常,java,exception,java-8,try-catch,Java,Exception,Java 8,Try Catch,在尝试我在m1()方法中找到的多捕获功能时,一切都正常 但是,在m2()中,不编译相同的代码。我刚刚更改了语法以减少代码行数 public class Main { public int m1(boolean bool) { try { if (bool) { throw new Excep1(); } throw new Excep2();

在尝试我在
m1()
方法中找到的多捕获功能时,一切都正常

但是,在
m2()
中,不编译相同的代码。我刚刚更改了语法以减少代码行数

public class Main {

    public int m1(boolean bool) {
        try {
            if (bool) {
                throw new Excep1();
            }
            throw new Excep2();
            //This m1() is compiling  abs fine.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    public int m2(boolean b) {
        try {
            throw b ? new Excep1() : new Excep2();
            //This one is not compiling.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    private static interface I {
    }

    private static class Excep1 extends Exception implements I {
    }

    private static class Excep2 extends Exception implements I {
    }
}

为什么方法
m2()
不编译?

表达式的类型

b ? new Excep1() : new Excep2()
Exception
,因为这是
Excep1
Excep2
的常见超类型

但是,您没有捕获异常,因此编译器会对此进行投诉

如果捕获异常,它将通过编译:

public int m2(boolean b) {
    try {
        throw b ? new Excep1() : new Excep2();
    } catch (Exception e) {
        return 0;
    }
}
我试图找到在您的示例中解释条件三元表达式类型的JLS条目

我所能找到的就是这个特殊的表达是一个

我不完全确定它是作为多边形表达式还是独立表达式。我认为它是独立的(因为poly表达式涉及赋值上下文或调用上下文,我不认为
throw
语句算作这两者之一)

对于独立表达式:“如果第二个和第三个操作数具有相同的类型(可能是null类型),则这是条件表达式的类型。”

在您的情况下,第二个和第三个操作数有三种常见类型—
对象
可丢弃
异常
——表达式的类型必须是后两种类型之一,因为“throw语句中的表达式必须表示可赋值的引用类型的变量或值(§5.2)到可丢弃的类型。”

编译器似乎选择了最具体的公共类型(
Exception
),因此
catch(Exception e)
解决了编译错误


我还尝试用两个子类
IOException
替换您的两个自定义异常,在这种情况下
catch(IOException e)
解决了编译错误。

您将编译器与以下行混淆:

throw b ? new Excep1() : new Excep2();

编译器看到表达式的结果(在抛出的右侧)是Except1和Except2之间的公共超类,它是Exception,因此要抛出的有效类型成为Exception。catch语句无法识别您试图抛出的异常1或异常2。

Java限制您捕获或声明该方法可以抛出的所有异常类型

它搜索两个(/all)异常的公共父级,并期望您捕获或声明为抛出,例如,如果
Excep1
extends
Throwable
您还必须捕获Throwable


在第一种情况下,Java确定您正在抛出
EXEP1
EXEP2

您得到了什么编译错误?@Smile三元条件表达式的类型必须对第二个和第三个操作数都是通用的。因此,它不能是
Excep1
Excep2
。它只能是
异常
。15.25.3中的最后一个要点给出了答案:否则,第二个和第三个操作数分别为S1和S2类型。设T1为将装箱转换应用于S1时产生的类型,设T2为将装箱转换应用于S2时产生的类型。条件表达式的类型是将捕获转换(§5.1.10)应用于lub(T1,T2)的结果。“这里的lub是最小上界,这是两个表达式类型共享的最接近的公共超类型。