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