【问题标题】:Using Ternary Operator to Throw Checked or Unchecked Exceptions使用三元运算符抛出已检查或未检查的异常
【发布时间】:2019-09-20 02:32:29
【问题描述】:

我最初的问题使用了FileNotFoundException 和IllegalStateException,因此它们包含在答案中。为了简单起见,我已将它们分别更改为它们的超类 IOException 和 RuntimeException。


这样编译(不使用三元,1 个选中,1 个未选中):

private void test() throws IOException { // throws is required
    if (new Random().nextInt(2)==0) throw new IOException();
    throw new RuntimeException();
}

这也可以编译(使用三元,2 个未经检查的异常):

private void test3() { // throws not required
    throw new Random().nextInt(2)==0 ? new UncheckedIOException(null) : new RuntimeException();
}

但是为什么这不能编译(使用三元,1 个选中,1 个未选中)?

private void test2() throws IOException {
    throw new Random().nextInt(2)==0 ? new IOException() : new RuntimeException();
}

来自 Eclipse:

未处理的异常类型Exception

提供 2 个快速修复:

J! 添加 throws 声明

J! 用 try/catch 包围


另外一对例子

这样编译:

private void test4() { // throws not required
    if (new Random().nextInt(2)==0) throw new Error();
    throw new RuntimeException();
}

这不是:

private void test5() {
    throw new Random().nextInt(2)==0 ? new Error() : new RuntimeException();
}

来自 Eclipse:

未处理的异常类型 Throwable

提供 2 个快速修复:

J! 添加 throws 声明

J! 用 try/catch 包围

【问题讨论】:

  • @NathanHughes 条件评估为boolean 。整个三元表达式不需要求值相同的类型,System.out.println(a == b? "yes" : 5) 就可以了。
  • @daniu 三元表达式被评估为Object,这是最常见的超类型
  • 关键是条件运算符不是if语句的简写。

标签: java exception ternary-operator


【解决方案1】:

为什么不编译?

因为在这种情况下,条件 ?: 运算符的推断类型是Exception,遵循JLS 15.25.3 的规则。虽然 JLS 很快变得复杂,但规则试图找到“最具体的类型,其中有两种操作数类型的隐式转换”。一种“最近的共同祖先”。

本例中的继承层次为:

                      Exception
                   /              \
           IOException           RuntimeException
               /                         \
      FileNotFoundException           IllegalStateException

...所以最近的共同祖先是Exception。您的代码有点相当于:

private void test() throws FileNotFoundException {
    Exception exception = 1==0 ? new FileNotFoundException() : new IllegalStateException();
    throw exception;
}

希望你已经明白为什么 会编译失败...在这种情况下,如果运气好的话,现在一切都清楚了 :)

【讨论】:

  • 如果通用类型是 Throwable (其中一种情况是 Error 什么的)会起作用吗?
  • @PaulStelian 除非你声明 test() throws Throwable.
  • @AndyTurner Throwable (Error etc) 可以在没有 throws 声明的情况下抛出,因此我的问题是成立的。只有什么是 Exception 而不是 RuntimeException 才需要 throws 声明。
  • @AndyTurner @Lino 所以实际上它是错误类型的一个特例,它没有被选中?
  • @PaulStelian 是的。 Error 和 RuntimeException(和子类)未选中;其他人被检查。
猜你喜欢
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多