如果我使用多个catch块,为什么java不检测不可达的catch块?

研究以下方法:

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 FilesJavajdk1.7.0_45bin>javac D:DNN-ProjectDNN-ProjectsrcmainjavaexceptionsAndAssertionsRethowTest.java
D:DNN-ProjectDNN-ProjectsrcmainjavaexceptionsAndAssertionsRethowTest.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-ProjectDNN-ProjectsrcmainjavaexceptionsAndAssertionsRethowTest.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 8 JLS 14.21(和Java 7)中定义如下:

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

  • C的参数类型是未检查的异常类型或Exception或Exception的超类, 或者try块中的某个表达式或throw语句是可访问的,并且可以抛出一个检查的异常,该异常的类型可分配给C的参数类型。 (如果包含它的最内层语句可以访问,则表达式是可访问的。)

    表达式的正常和突然完成见§15.6。

  • 在try语句中没有早先的catch块A,使得C的参数类型与A的参数类型相同或是其类型的子类。

  • 请注意,规则不禁止您的示例代码。 第二个catch块不符合第二个项目符号的标准。

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

    这是否不一致? 对于你的例子,你可能会认为是这样。

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

  • 可达性规则的制定将需要显着更复杂来处理这个问题。 规范中额外(不必要的)复杂性是一个问题。

  • 你可能会认为这种不一致并没有破坏任何东西。 可达性规则实际上只是一种挑选用户代码中潜在错误的方法。 它不涉及类型安全或可预测的执行; 即会“破坏”Java运行时语义的东西。

  • 如果他们现在改变了规范,那么会导致一小部分有效和正在运行的Java程序失效。 这不是一个好主意,因为稳定性是Java的主要卖点之一。

  • 另一方面,我想不出他们为什么不能解决规范中的这种“不一致性”的技术原因。


    您注意到一些Java编译器在第二个catch上给出了警告消息。 那没问题。 Java编译器允许为(技术上)合法的Java代码提供警告。

    如果他们是错误的,那在技术上会是一个编译器错误......根据我对JLS的阅读。


    catch (Exception ...)块会捕获运行时异常。 原则上永远不可能达到。

    FileNotFoundException是一个检查的异常。 如果try块中的某个内容抛出它或其子类之一,那么它的catch块才是可访问的。

    [回应请求]


    如果实例化new FileNotFoundException() ,则调用Class FileNotFoundException的构造FileNotFoundException 。 在这个构造函数中,可以通过调用本地方法fillInStackTrace来抛出IOException - 编译器可能不知道构造函数的内容是什么,可能会抛出IOException

    请参阅此文章:https://community.oracle.com/thread/1445008?start=0例如。

    如果编译器查看每个occourcence的构造函数FileNotFoundException() :它的开销java忽略了性能。

    链接地址: http://www.djcxy.com/p/81207.html

    上一篇: Why does not java detect unreachable catch block if I use multiple catch blocks?

    下一篇: How to detect resize of any element in HTML5