在没有声明的情况下,为什么在某些情况下重新抛出Throwable是合法的? [英] Why is it legal to re-throw a Throwable in certain cases, without declaring it?

查看:297
本文介绍了在没有声明的情况下,为什么在某些情况下重新抛出Throwable是合法的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望以下代码在 throw t; 上引发编译时错误,因为 main 是未声明抛出 Throwable ,但它成功编译(在Java 1.7.0_45中),并且如果修复了编译时错误,则产生您期望的输出。 / p>

I would expect the following code to raise a compile-time error on throw t;, because main is not declared to throw Throwable, but it compiles successfully (in Java 1.7.0_45), and produces the output you would expect it to if that compile-time error was fixed.

public class Test {
    public static void main(String[] args) {
        try {
            throw new NullPointerException();

        } catch(Throwable t) {
            System.out.println("Caught "+t);
            throw t;
        }
    }
}

如果<$还会编译c $ c> Throwable 更改为 Exception

这不能编译,正如所料:

This does not compile, as expected:

public class Test {
    public static void main(String[] args) {
        try {
            throw new NullPointerException();

        } catch(Throwable t) {
            Throwable t2 = t;
            System.out.println("Caught "+t2);
            throw t2;
        }
    }
}

这个编译:

public class Test {
    public static void main(String[] args) {
        try {
            throwsRuntimeException();

        } catch(Throwable t) {
            System.out.println("Caught "+t);
            throw t;
        }
    }

    public static void throwsRuntimeException() {
        throw new NullPointerException();
    }
}

这不是:

public class Test {
    public static void main(String[] args) {
        try {
            throwsCheckedException();

        } catch(Throwable t) {
            System.out.println("Caught "+t);
            throw t;
        }
    }

    public static void throwsCheckedException() {
        throw new java.io.IOException();
    }
}

此编译:

public class Test {
    public static void main(String[] args) throws java.io.IOException {
        try {
            throwsIOException();

        } catch(Throwable t) {
            System.out.println("Caught "+t);
            throw t;
        }
    }

    public static void throwsIOException() throws java.io.IOException {
        throw new java.io.IOException();
    }
}

一个更复杂的例子 - 被检查的异常被捕获外部捕获块,而不是声明被抛出。这个编译:

A more complex example - the checked exception is caught by an outer catch block, instead of being declared to be thrown. This compiles:

public class Test {
    public static void main(String[] args) {
        try {
            try {
                throwsIOException();

            } catch(Throwable t) {
                System.out.println("Caught "+t);
                throw t;
            }
        } catch(java.io.IOException e) {
            System.out.println("Caught IOException (outer block)");
        }
    }

    public static void throwsIOException() throws java.io.IOException {
        throw new java.io.IOException();
    }
}

所以似乎有一个特殊情况允许重新抛出编译器可以确定捕获的异常总是合法的重新抛出时的异常。它是否正确?这在JLS中指定了哪里?还有其他像这样模糊不清的角落吗?

So there seems to be a special case to allow rethrowing exceptions when the compiler can determine that the caught exception is always legal to re-throw. Is this correct? Where is this specified in the JLS? Are there any other obscure corner-cases like this?

推荐答案

这是由 JLS 11.2.2 (强调我的):


抛出表达式为的最终或有效最终异常参数的抛出语句C可以抛出异常类E iff:


  • E是一个异常类,声明C可以抛出的try语句的try块;和

  • E is an exception class that the try block of the try statement which declares C can throw; and

E与任何C的可捕获异常类兼容;和

(...)

换句话说, E ,文档中引用的类型是可以抛出的类型,而不是类型catch子句参数捕获它( catchable exception class )。它必须与catch子句参数赋值兼容,但参数的类型不用于分析。

In other words, E, the type referenced in the doc, is the type that can be thrown, not the type of the catch clause parameter that catches it (the catchable exception class). It just has to be assignment compatible to the catch clause parameter, but the parameter's type is not used in analysis.

这就是为什么去在他们的方式中说一个最终或有效的最终异常参数 - 如果你的例子中的 t 被重新分配,分析就会消失在窗外。

This is why the go out of their way to say a final or effectively final exception parameter--if t in your example were reassigned, the analysis would go out the window.

这篇关于在没有声明的情况下,为什么在某些情况下重新抛出Throwable是合法的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆