无法访问的代码编译器错误

ugh*_*zan 25 java compiler-construction

以下代码给出了unreachable statement编译器错误

public static void main(String[] args) {
    return;
    System.out.println("unreachable");
}
Run Code Online (Sandbox Code Playgroud)

有时为了测试目的,希望阻止调用方法,因此快速执行此操作(而不是在使用它的任何地方对其进行注释)是立即从方法返回,以便该方法不执行任何操作.然后我总是这样做以解决编译器错误

public static void main(String[] args) {
    if (true) {
        return;
    }
    System.out.println("unreachable");
}
Run Code Online (Sandbox Code Playgroud)

我只是好奇,为什么它是一个编译错误?它会以某种方式打破Java字节码,它是为了保护程序员还是其他东西?

另外(这对我来说更有趣),如果编译java到字节码进行任何类型的优化(或者即使它没有)那么为什么它不会在第二个例子中检测到明显无法访问的代码呢?编译器伪代码用于检查语句是否无法访问?

And*_*dré 22

无法访问的代码没有意义,因此编译时错误很有帮助.在第二个示例中不会检测到它的原因是,如您所料,用于测试/调试目的.它在规范中解释:

if (false) { x=3; }
Run Code Online (Sandbox Code Playgroud)

不会导致编译时错误.优化编译器可以实现语句x = 3; 将永远不会执行,并可能选择从生成的类文件中省略该语句的代码,但语句x = 3; 在此处指定的技术意义上,不被视为"无法到达".

这种不同处理的基本原理是允许程序员定义"标志变量",例如:

static final boolean DEBUG = false;
Run Code Online (Sandbox Code Playgroud)

然后编写如下代码:

if (DEBUG) { x=3; }
Run Code Online (Sandbox Code Playgroud)

我们的想法是,应该可以将DEBUG的值从false更改为true或从true更改为false,然后正确编译代码而不对程序文本进行其他更改.

参考:http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21

  • `if(DEBUG)`与`if(true)`完全相同.`DEBUG`是一个常量变量,因为它是final的,并用编译时常量表达式初始化.`true`是原始类型的文字,因此也是一个常量表达式.即使有可能区分这两者,这只会引起混淆.人们会问:为什么`if(DEBUG)`**但不是**if(true)`? (4认同)

小智 7

这是因为编译器编写者认为控件中的人是愚蠢的,并且可能并不意味着添加永远不会执行的代码 - 因此通过抛出错误,它会试图阻止您无意中创建一个无法执行的代码路径执行 - 而不是强迫你做出决定(即使你已经证明,你仍然可以解决它).

  • 但如果它只是一个快速测试,它可能没有错。 (2认同)