如果我使用多个捕获块,为什么Java无法检测到无法到达的捕获块?

问题描述 投票:8回答:3

研究以下方法:

static private void foo()  {
        try {
            throw new FileNotFoundException();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

尽管最后一个catch块实际上无法到达,但此代码编译良好。

现在让注释throw new FileNotFoundException();

执行:

糟糕!我们看到

Unreachable catch block for FileNotFoundException. This exception is never thrown from the try statement body

奇怪。为什么Java对这些情况使用双重标准?

@ Peter Rader的更新

static private void foo(FileNotFoundException f)  {
        try {
            throw f;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

工作以及构造函数调用

更新

[我注意到在不同版本的Java编译器上,我看到的编译此代码的结果不同。

public class RethowTest {

        public static void main(String[] args)  {
            try {
                throw new FileNotFoundException();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                throw e;
            }
        }    
}

在我的本地计算机上:Java 1.7.0_45-

C:\Program Files\Java\jdk1.7.0_45\bin>javac D:\DNN-Project\DNN-Project\src\main\java\exceptionsAndAssertions\RethowTest.java
D:\DNN-Project\DNN-Project\src\main\java\exceptionsAndAssertions\RethowTest.java:15: warning: unreachable catch clause
                } catch (IOException e) {
                  ^
  thrown type FileNotFoundException has already been caught
1 warning

java 1.6.0_38

D:\DNN-Project\DNN-Project\src\main\java\exceptionsAndAssertions\RethowTest.java:16: unreported exception java.io.IOException; must be caught or declared to be thrown
                    throw e;
                    ^
1 error

http://www.compileonline.com/compile_java_online.php(Javac 1.7.0_09)-

HelloWorld.java:9: warning: unreachable catch clause
        } catch (IOException e) {
          ^
  thrown type FileNotFoundException has already been caught
1 warning
java exception try-catch unreachable-code
3个回答
6
投票

可达性规则在Java 8 JLS 14.21(和Java 7)中定义如下:

如果满足以下两个条件,则可以到达捕获块C:

  • C的参数类型是未经检查的异常类型或Exception或Exception的超类, C的参数。(如果包含表达式的最里面的语句是可到达的,则该表达式可到达。)

    请参见§15.6中有关表达式的正常和突然完成。
  • try语句中没有较早的catch块A,因此C的参数类型与A的参数类型相同或是其子类。

注意,规则不禁止您的示例代码。第二个捕获块不符合第二个要点的标准。

((在示例的原始版本中,您捕获了Exception。可及性推理将有所不同,但答案是相同的-有效代码。)

这是不一致的吗?以您的示例为例,您可能会说是这样。

为什么他们没有在可达性规则中解决这个问题?我不知道。您需要询问Java设计师!!但是:

可及性规则的

  • formulation可能需要更加复杂才能处理。规范中额外的(不必要的?)复杂性值得关注。

  • 您可能会说这种不一致不会破坏任何东西。可达性规则实际上只是在用户代码中拾取

    potential

  • 错误的一种方式。它不涉及类型安全或可预测的执行;即会“破坏” Java运行时语义的内容。
  • 如果他们现在更改了规范,那将使一小部分有效且有效的Java程序无效。考虑到稳定性是Java的主要卖点之一,所以这不是一个好主意。

另一方面,我无法想到他们

无法在规范中解决此“不一致”的技术原因。


[您注意到,某些Java编译器在第二个catch发出警告消息。那没问题。允许Java编译器对(技术上)合法的Java代码发出警告。

如果它们是错误,从技术上讲,这将是编译器的错误……根据我对JLS的阅读。


1
投票
catch (Exception ...)块将捕获运行时异常。从原则上讲,它永远不会到达。

FileNotFoundException是已检查的异常。一个catch块只有在try块中的某个东西抛出它或其子类之一时才可以到达。

[响应请求]


-3
投票
如果实例化为new FileNotFoundException(),则称为类FileNotFoundException的构造函数。在此构造函数中,可以通过调用本机方法fillInStackTrace从理论上引发IOException-编译器可能不知道构造函数的内容,可能会抛出IOException

[查看本文:https://community.oracle.com/thread/1445008?start=0示例。

如果编译器在每次出现时都在构造函数FileNotFoundException()中使用它:忽略了Java的性能开销。]

© www.soinside.com 2019 - 2024. All rights reserved.