在 Java-8 中捕获多个异常
Posted
技术标签:
【中文标题】在 Java-8 中捕获多个异常【英文标题】:Catching multiple exceptions in Java-8 【发布时间】:2020-04-26 23:32:49 【问题描述】:在尝试我在 m1()
方法中发现的 multi-catch 功能时,一切正常。
但是,在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()
不编译?
【问题讨论】:
你遇到了什么编译错误? 【参考方案1】:表达式的类型
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. Reference Conditional Expression。
我不完全确定它是否算作多边形表达式或独立表达式。我认为它是独立的(因为 poly 表达式涉及赋值上下文或调用上下文,我不认为 throw
语句算作其中任何一个)。
对于独立表达式:“如果第二个和第三个操作数具有相同的类型(可能是空类型),那么这就是条件表达式的类型。”
在您的情况下,第二个和第三个操作数具有三种常见类型 - Object
、Throwable
和 Exception
- 表达式的类型必须是后两者之一,因为“The Expression in a throw语句必须表示一个变量或引用类型的值,该引用类型可分配(第 5.2 节)给 Throwable 类型。”
编译器似乎选择了最具体的常见类型 (Exception
),因此 catch (Exception e)
解决了编译错误。
我还尝试用IOException
的两个子类替换你的两个自定义异常,在这种情况下catch (IOException e)
解决了编译错误。
【讨论】:
@Smile 三元条件表达式的类型必须为第二个和第三个操作数所共有。因此它不能是Excep1
或Excep2
。只能是Exception
。
15.25.3 中的最后一个要点有答案:“否则,第二个和第三个操作数分别为 S1 和 S2 类型。令 T1 为对 S1 应用装箱转换后的类型,并令 T2 为将装箱转换应用于 S2 的类型。条件表达式的类型是将捕获转换 (§5.1.10) 应用于 lub(T1, T2) 的结果。这里的 lub 是 Least Upper Bound,这是两个表达式的类型共享的最接近的公共超类型。【参考方案2】:
您将编译器与这一行混淆了:
throw b ? new Excep1() : new Excep2();
编译器看到表达式的结果(在throw的右边)是Except1和Exception2之间的公共超类,即Exception,因此你抛出的有效类型变成了Exception。 catch 语句无法识别您正在尝试抛出异常 1 或异常 2。
【讨论】:
【参考方案3】:Java 限制您捕获或声明该方法可以抛出的所有异常类型,
它为两个 (/all) 异常搜索公共父级,并期望您捕获或声明为 throws,例如,如果 Excep1
扩展 Throwable
您还必须捕获 Throwable
在第一种情况下,Java 确定您正在抛出 Excep1
或 Excep2
【讨论】:
以上是关于在 Java-8 中捕获多个异常的主要内容,如果未能解决你的问题,请参考以下文章