java - 重新抛出异常 : Why does the method compile without a throws clause?

标签 java

在下面的源代码中,我正在重新抛出 Exception
为什么不需要在方法的签名上加上throws关键字?

public void throwsOrNotThrowsThatsTheQuestion() {
    try {

        // Any processing

    } catch (Exception e) {
        throw e;
    }
}

最佳答案

这种行为似乎只发生在 Java 1.7 上。使用 1.6 编译时,我收到以下编译器错误消息:

c:\dev\src\misc>javac -source 1.6 Main.java
warning: [options] bootstrap class path not set in conjunction with -source 1.6
Main.java:22: error: unreported exception Exception; must be caught or declared
to be thrown
        throw e;
        ^
1 error
1 warning

但是对于 Java 1.7,它可以编译。

c:\dev\src\misc>javac -source 1.7 Main.java

c:\dev\src\misc>

...直到我在 try block 中实际抛出 Exception:

public static void throwsOrNotThrowsThatsTheQuestion() {
try {

    // Any processing
    throw new IOException("Fake!");

} catch (Exception e) {
    throw e;
}

正在编译...

c:\dev\src\misc>javac -source 1.7 Main.java
Main.java:22: error: unreported exception IOException; must be caught or declare
d to be thrown
        throw e;
        ^
1 error

看起来 Java 1.7 已经足够智能,可以通过分析 try block 代码来检测可能引发的 Exception(s) 类型,而 1.6 刚刚看到throw e; 类型 Exception 并为此给出错误。

将其更改为抛出 RuntimeException 使其按预期编译,因为与往常一样,未经检查的 Exception 不需要 throws 子句:

public static void throwsOrNotThrowsThatsTheQuestion() {
try {

    // Any processing
    throw new RuntimeException("Fake!");

} catch (Exception e) {
    throw e;
}

正在编译...

c:\dev\src\misc>javac -source 1.7 Main.java

c:\dev\src\misc>

解释

这是怎么回事:

Java 7 引入 more inclusive type checking .引用...

Consider the following example:

static class FirstException extends Exception { }
static class SecondException extends Exception { }

public void rethrowException(String exceptionName) throws Exception {
  try {
    if (exceptionName.equals("First")) {
      throw new FirstException();
    } else {
      throw new SecondException();
    }
  } catch (Exception e) {
    throw e;
  }
}

This examples's try block could throw either FirstException or SecondException. Suppose you want to specify these exception types in the throws clause of the rethrowException method declaration. In releases prior to Java SE 7, you cannot do so. Because the exception parameter of the catch clause, e, is type Exception, and the catch block rethrows the exception parameter e, you can only specify the exception type Exception in the throws clause of the rethrowException method declaration.

However, in Java SE 7, you can specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration. The Java SE 7 compiler can determine that the exception thrown by the statement throw e must have come from the try block, and the only exceptions thrown by the try block can be FirstException and SecondException. Even though the exception parameter of the catch clause, e, is type Exception, the compiler can determine that it is an instance of either FirstException or SecondException:

(强调我的)

public void rethrowException(String exceptionName)
throws FirstException, SecondException {
  try {
    // ...
  }
  catch (Exception e) {
    throw e;
  }
}

关于java - 重新抛出异常 : Why does the method compile without a throws clause?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19913834/

相关文章:

java - Reactor/WebFlux 实现了一个响应式的 http 新闻自动收报机

java - 时间到期时从 Recyclerview 中删除项目

java - 如何在 Java 中使用反射获取 Enum 字段名称?

Java8 方法引用用作函数对象以组合函数

java - 使用 Java DOM 调用 getAttributeNS 的正确方法是什么?

java - java 如何删除指向数组中元素的指针

java - Android UI - 在中心对齐按钮,垂直排序

java - 同时使用两个路由器配置的 Akka 路由

java - JSP 应用程序 - 使用 Context.xml 环境标记的全局变量列表

java - 尝试在 Android Studio 上启动我的第三个 Activity 时被重定向到初始 Activity