使用三元运算符抛出已检查或未检查的异常

Using Ternary Operator to Throw Checked or Unchecked Exceptions

我原来的问题使用了 FileNotFoundExceptionIllegalStateException,因此它们包含在答案中。为了简单起见,我分别将它们更改为超类 IOExceptionRuntimeException


此编译(不使用三进制,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:

Unhandled exception type Exception

2 quick fixes available:

J! Add throws declaration

J! Surround with 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:

Unhandled exception type Throwable

2 quick fixes available:

J! Add throws declaration

J! Surround with try/catch

Why does this not compile?

因为条件运算符 ?: 的推断类型在这种情况下是 Exception,遵循 JLS 15.25.3 的规则。虽然 JLS 变得非常复杂,但规则正在尝试找到 "the most specific type where there's an implicit conversion from both of the operand types"。一种 "nearest common ancestor".

本例中的继承层次为:

                      Exception
                   /              \
           IOException           RuntimeException
               /                         \
      FileNotFoundException           IllegalStateException

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

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

希望您已经明白为什么 that 会编译失败...如果幸运的话,现在一切都清楚了:)