以下代码给出了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到字节码进行任何类型的优化(或者即使它没有)那么为什么它不会在第二个例子中检测到明显无法访问的代码呢?编译器伪代码用于检查语句是否无法访问?
答案 0 :(得分:22)
无法访问的代码毫无意义,因此编译时错误很有帮助。在第二个示例中不会检测到它的原因是,如您所料,用于测试/调试目的。它在规范中解释:
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
答案 1 :(得分:7)
这是因为编译器编写者认为控件中的人是愚蠢的,并且可能并不意味着添加永远不会执行的代码 - 因此通过抛出错误,它会试图阻止您无意中创建代码路径这是无法执行的 - 而是迫使你做出决定(即使你已经证明,你仍然可以解决它)。
答案 2 :(得分:2)
此错误主要是为了防止程序员错误(交换2行或更多行)。在第二个片段中,您清楚地表明您不关心system.out.println()。
答案 3 :(得分:2)
它会以某种方式破坏Java字节码,它是为了保护程序员还是其他东西?
就Java / JVM而言,这不是必需的。编译错误的唯一目的是避免程序员的愚蠢错误。请考虑以下JavaScript代码:
function f() {
return
{
answer: 42
}
}
此函数返回undefined
,因为JavaScript引擎在行尾添加分号并忽略死代码(正如它所认为的那样)。 Java编译器更聪明,当它发现你正在做一些清楚而明显错误的事情时,它不会让你这样做。你本来没有办法打算使用死码。这在某种程度上符合Java作为安全语言的前提。
答案 4 :(得分:0)
在第一种情况下,您在任何语句之前返回,因为它编译器永远不会执行该代码。
在第二个代码中,我将声明置于返回及其工作之上:)
这背后的原因是,如果你返回某个时间,那么代码永远不会执行,因为你已经返回了函数数据,因此它显示为无法访问的代码。
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;
}
答案 5 :(得分:0)
http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21
表示:
14.21。无法访问的语句
如果语句因无法访问而无法执行,则为编译时错误。
答案 6 :(得分:-1)
这是因为即使在那里也浪费资源。此外,编译器设计人员不想假设他们可以删除的内容,而是强迫您删除使其无法访问的代码或无法访问的代码本身。他们不知道那里应该是什么。优化之间存在差异,它们将代码调整为在编译为机器代码时更高效,并且公然只删除“您不需要的代码”。