为什么Java编译器拒绝将System.exit()识别为过程终止?

Tyl*_*den 4 java compiler-errors

Java的编译器,至少是我使用的Oracle编译器,拒绝将System.exit()识别为过程终止.例如,以下代码给出了编译错误:

public static int readInteger( ArrayList<String> listLines, int iLineNumber0 ){
    try {
        int value = Integer.parseInt( listLines.get( 0 ) );
        return value;
    } catch( Throwable t ) {
        System.err.println( "error reading line: " + iLineNumber0 + ": " + t );
        System.exit( -1 );
    }
}
Run Code Online (Sandbox Code Playgroud)

错误是:"缺少返回语句." 因此,为了完成这项工作,我必须在这样的返回语句中添加(编译成功):

public static int readInteger( ArrayList<String> listLines, int iLineNumber0 ){
    try {
        int value = Integer.parseInt( listLines.get( 0 ) );
        return value;
    } catch( Throwable t ) {
        System.err.println( "error reading line: " + iLineNumber0 + ": " + t );
        System.exit( -1 );
    }
    return 0; // unreachable code
}
Run Code Online (Sandbox Code Playgroud)

具有讽刺意味的是,所需的最终返回语句是无法访问的代码,尽管编译器也没有意识到这一点.

Jon*_*eet 10

Java的编译器,至少是我使用的Oracle编译器,拒绝将System.exit()识别为过程终止.

是的,它会的.就编译器而言,它只是一种void方法.在方法签名中无法指示"此方法永远不会正常返回",并且语言中没有这样的概念.例如:

public void alwaysThrow()
{
    throw new RuntimeException();
}

...

alwaysThrow();
System.out.println("This line is never reached");
Run Code Online (Sandbox Code Playgroud)

就编译器而言,上述代码段中的最后一行仍然可以访问,即使我们知道它永远不会执行.同样,您的额外退货声明在技术上是可达的,但实际上无法到达.

基本上这可能被认为是语言中的一个缺陷,尽管据我所知,它会影响大多数语言.虽然能够代表这样的方法会很好,但它在现实生活中很少成为真正的问题.

如果你发现自己被它困扰,你可以编写一个辅助方法:

public RuntimeException systemExit(int exitValue)
{
    System.exit(exitValue);
    return new RuntimeException("Shouldn't get here");
}
Run Code Online (Sandbox Code Playgroud)

然后将其称为:

throw systemExit();
Run Code Online (Sandbox Code Playgroud)

这将确保在编译器方面无法访问语句的结尾,因此您可以:

catch (Throwable t) {
    System.err.println("error reading line: " + iLineNumber0 + ": " + t);
    throw systemExit(-1);
}
Run Code Online (Sandbox Code Playgroud)

...并且你的编译器错误会消失.

请注意,还有其他类似情况,可达性不是我们可能想要的所有内容.例如:

int foo() {
    int x = someValue();
    if (x > 10) {
       return 1;
    }
    if (x <= 10) {
       return 20;
    }
    // Is this reachable or not?
}
Run Code Online (Sandbox Code Playgroud)

我们知道任何值都x将大于10或小于或等于10,因此最后一行几乎无法访问,但语言规则并未表达......所以即使是智能编译器也是如此在不违反语言规范的情况下,实际上不能将上述代码视为有效.

  • @Absurd-Mind:智能编译器可以检测到它,但它不能将其视为有效的Java代码,因为Java规范只是*无效*. (3认同)