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

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

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

有时为了测试目的,想要阻止一个方法被调用,所以快速的方法(而不是在它使用的任何地方注释它)是立即从方法返回,以便该方法什么都不做。 然后,我总是这样做以解决编译器错误

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

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

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

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

 if (false) { x=3; } 

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

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

 static final boolean DEBUG = false; 

然后编写如下代码:

 if (DEBUG) { x=3; } 

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

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

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

此错误主要是为了防止程序员错误(交换2行或更多行)。 在第二个片段中,您清楚地表明您不关心system.out.println()。

它会以某种方式打破Java字节码,它是为了保护程序员还是其他东西?

就Java / JVM而言,这不是必需的。 编译错误的唯一目的是避免愚蠢的程序员错误。 请考虑以下JavaScript代码:

 function f() { return { answer: 42 } } 

此函数返回undefined因为JavaScript引擎在行尾添加分号并忽略死代码(如它认为的那样)。 Java编译器更聪明,当它发现你正在做一些清楚而明显错误的事情时,它不会让你这样做。 你本来没有办法打算使用死码。 这在某种程度上符合Java作为安全语言的前提。

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

说:

14.21。 无法访问的语句

如果由于无法访问语句而无法执行语句,则会发生编译时错误。

在第一种情况下,您在任何语句之前返回,因为它编译器永远不会执行该代码。

在第二个代码中,我已将声明置于返回上面并且现在正在工作:)

这背后的原因是,如果你返回某个时间,那么代码永远不会执行,因为你已经返回了函数数据,因此显示无法访问的代码。

public static void main(String [] args){

 return; System.out.println("unreachable"); 

}

/////////////////////////////////

public static void main(String [] args){

 System.out.println("unreachable"); // Put the statement before return return; 

}

这是因为即使在那里也浪费资源。 此外,编译器设计人员不想假设他们可以删除的内容,而是强迫您删除使其无法访问的代码或无法访问的代码本身。 他们不知道那里应该是什么。 优化之间存在差异,它们将代码调整为在编译为机器代码时更高效,并且公然只删除“您不需要”的代码。