为什么这些重新抛出的异常中的任何一个都会产生编译器错误?

Why do either of these rethrown exceptions create a compiler error?

为什么throw outerE;会产生编译错误?我知道 throw e; 不应生成编译器错误,因为 precise rethrow feature.

它们是相同的 Exception 对象,但一个只在 catch 块内,一个在 try-catch 块外。

这些都不应该产生编译器错误吗?或者,至少,两者的行为方式相同?

static void preciseRethrowTest()
{
    Exception outerE;
    try
    {

    }
    catch (Exception e)
    {
        outerE = e;

        // Compilation error here. Unhandled exception type Exception
        // throw outerE; 

        throw e; // No compiler error
    }
}

我正在使用 Java 1.8.0_51。 (精确重抛在Java7中介绍)

问题是检查异常无法到达catch块;编译器足够聪明,可以实现这一点。

考虑一下:

public class RethrowTest {
  static void preciseRethrowTest() {
    Exception outerE;
    try {
      throw new Exception();
    } catch (Exception e) {
      outerE = e;

      // Compilation error here. Unhandled exception type Exception
      // throw outerE;

      throw e; // Now a compiler error *is* generated.
    }
  }
}

抛出一个编译器错误,因为代码现在可以通过检查的异常到达。

您的方法没有 throws 声明。

编译器现在足够聪明,可以确定您的 try 块不能抛出任何已检查的异常。因此,必须取消选中 catch 块中捕获并绑定到 Exception 参数的任何异常。由于它们未经检查,您可以在闲暇时重新抛出它们(它们不需要 throws 声明)。

在这里,您正在尝试重新分配

outerE = e;
// Compilation error here. Unhandled exception type Exception
// throw outerE; 

并通过不同的变量重新抛出异常。编译器不会走那么远来弄清楚 outerE 中的值是什么。它可能是您捕获的异常,也可能是其他原因。编译器谨慎行事并阻止您这样做。

考虑像这样的代码

if (Math.random() < 0.5) 
    outerE = e;
else 
    outerE = new IOException("nope");
throw outerE; 

编译器无法知道存储在 outerE 中的 Exception 值是您捕获的未经检查的异常还是您从其他地方分配的其他可能已检查的异常。