编译器不抱怨我捕获了一个永远不会被抛出的异常

时间:2015-01-25 08:23:23

标签: java exception-handling

我正在阅读java 7 http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html中更精确的重新定义,其中说

  

详细说明,在Java SE 7及更高版本中,当您声明一个或多个时   catch子句中的异常类型,并重新抛出处理的异常   通过此catch块,编译器验证该类型   rethrown异常符合以下条件:

The try block is able to throw it.
There are no other preceding catch blocks that can handle it.
It is a subtype or supertype of one of the catch clause's exception parameters.

所以我写了一个程序来测试它。

public class MorePreciseRethrow {
    public static void main(String args[]){
        try {
            foo("First");
        } catch (FirstException e) {
            e.printStackTrace();
        } catch (SecondException e) {
            e.printStackTrace();
        }
    }

    private static void foo(String exceptionName) throws FirstException, SecondException{
        try{
            if(StringUtils.equals("First",exceptionName)){
                throw new FirstException();
            }
        }catch(Exception e){
            throw e;
        }
    }
}

class FirstException extends Exception{

}

class SecondException extends Exception{

}

但是这甚至不会生成jdk7的编译器警告。 现在我的try块永远不能抛出SecondException,但我的编译器没有检查它。 doc中提到的行是错误的还是我做错了?

3 个答案:

答案 0 :(得分:3)

编译器仅检查方法头

private static void foo(String exceptionName) throws FirstException, SecondException

声明thr异常。

您可以有多个方法实现,因此一个实现可以抛出异常,而不是。但两者都必须被宣布。

答案 1 :(得分:2)

在java中,没有要求声明它throws异常的方法中的代码实际上能够抛出它。

这是有道理的,因为该方法可能正在实现一个接口,但实现恰好不会抛出它,或者它可能允许将来扩展到实际抛出它的实现/子类。

答案 2 :(得分:1)

为了获得文档所讨论的编译错误,您需要使用multiple catch。像,

private static void foo(String exceptionName) throws FirstException,
        SecondException {
    try {
        throw new FirstException();
    } catch (FirstException | SecondException e) {
        throw e;
    }
}

在Java 7 +中为UnreachableCodeBlock创建SecondException