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

时间:2015-08-13 14:49:35

标签: java exception exception-handling throws

为什么throw outerE;会产生编译错误?我知道由于precise rethrow feature.

throw e;不应该生成编译器错误

它们是相同的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。 (精确的重新抛出在Java 7中引入)

2 个答案:

答案 0 :(得分:6)

您的方法没有throws声明。

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

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

答案 1 :(得分:1)

问题是检查异常无法到达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.
    }
  }
}

会抛出编译错误,因为现在可以通过已检查的异常访问代码。