在尝试在我的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()不编译?
发布于 2020-01-09 11:14:02
表达式的类型
b ? new Excep1() : new Excep2()是Exception,因为这是Excep1和Excep2的常见超级类型。
但是,您没有捕获Exception,所以编译器会抱怨它。
如果捕获Exception,它将通过编译:
public int m2(boolean b) {
try {
throw b ? new Excep1() : new Excep2();
} catch (Exception e) {
return 0;
}
}我试图在您的示例中找到解释条件三元表达式类型的JLS条目。
我所能找到的就是这个特殊的表达式是一个15.25.3。参考条件表达式。
我不完全确定它是一个复合表达式还是一个独立表达式。我认为它是独立的(因为多表达式涉及赋值上下文或调用上下文,而且我不认为throw语句就是其中之一)。
对于独立表达式:“如果第二个和第三个操作数具有相同的类型(这可能是空类型),那么这就是条件表达式的类型。”
在您的示例中,第二个和第三个操作数有三种常见类型-- Object、Throwable和Exception --表达式的类型必须是后两种类型之一,因为“抛出语句中的表达式必须表示可分配给类型Throwable的引用类型的变量或值(§5.2)”。
编译器似乎选择了最特定的公共类型(Exception),因此catch (Exception e)解决了编译错误。
我还尝试用IOException的两个子类替换两个自定义异常,在这种情况下,catch (IOException e)解决了编译错误。
发布于 2020-01-09 11:19:56
您将编译器与这一行混淆在一起:
throw b ? new Excep1() : new Excep2();编译器看到表达式的结果(抛出的右边)是Except1和Except2之间常见的超类,这是异常,因此抛出的有效类型变成异常。catch语句无法获取您试图抛出的Excep1或Except2。
发布于 2020-01-09 11:20:27
Java限制您捕获或声明方法可以抛出的所有异常类型,
它搜索两个(/all)异常的公共父级,并期望您捕获或声明为抛出,例如,如果Excep1扩展了Throwable,那么您也必须捕获Throwable。
在第一种情况下,Java确信您正在抛出Excep1或Excep2
https://stackoverflow.com/questions/59662659
复制相似问题