从JDK 1.7开始,从catch块抛出异常对象不需要throws子句!!! 为什么会这样?

Aru*_*vaS 5 java exception-handling exception java-7 java-8

今天我在Java中遇到了一个奇怪的场景.我在我的方法中有一个try..catch块,它没有任何throws子句,我能够抛出catch块中捕获的异常对象.它是Exception类的对象,因此它不是未经检查的异常.此外,如果出现异常,它不会打印堆栈跟踪,而是异常被吞没.

下面是我的代码示例,

public class ExceptionTest {

    public void test() {
        try
        {
            // Some code which may throw exception.
        }
        catch(Exception ex)
        {
            // Compiler should ask me to have a *throws Exception* in the signature, when I am throwing an exception object.
            throw ex;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

但是,如果我抛出一个新的异常对象而不是捕获的异常对象,编译器会要求我在方法签名中有一个throws子句.

注意:在Java 7或8中运行时,我遇到了这种情况.

我想知道,抛出的物体在哪里?有任何想法的人请...

Jon*_*eet 13

如果try块中的代码不能抛出任何已检查的异常,您将看到这一点.此时,编译器知道该catch块捕获的唯一类型的异常必须是未经检查的异常,因此可以重新抛出它.请注意,如果您excatch块中分配了不同的值,则编译器将无法再获得该保证.目前,ex实际上是最终的.

如果您尝试调用声明在try块中抛出已检查异常的内容,则代码将无法按预期进行编译.

例如:

public class ExceptionTest {

    public void test() {
        try {
            foo();
        } catch(Exception ex) {
            throw ex;
        }
    }

    public void foo() throws java.io.IOException {
    }
}
Run Code Online (Sandbox Code Playgroud)

给出错误:

ExceptionTest.java:12: error: unreported exception IOException; must be caught or declared to be thrown
        throw ex;
        ^
Run Code Online (Sandbox Code Playgroud)

至于异常"去"的地方 - 如果try块中的代码抛出未经检查的异常,它将正常传播.试试这个:

public class ExceptionTest {

    public static void main(String[] args) {
        test();
    }

    public static void test() {
        try {
            String x = null;
            x.length();
        } catch(Exception ex) {
            throw ex;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,运行它会提供以下输出:

Exception in thread "main" java.lang.NullPointerException
        at ExceptionTest.test(ExceptionTest.java:10)
        at ExceptionTest.main(ExceptionTest.java:4)
Run Code Online (Sandbox Code Playgroud)

JLS 11.2.2记录了语句可以抛出的异常 - 只有在没有可以抛出的已检查异常的情况下,才会编译代码.