为什么Java有“无法访问的语句”编译器错误?

我经常发现在调试程序时,在代码块中插入 return 语句很方便(尽管可以说是不好的做法)。我可能会在Java中尝试类似的东西....

class Test {
        public static void main(String args[]) {
                System.out.println("hello world");
                return;
                System.out.println("i think this line might cause a problem");
        }
}

当然,这会产生编译器错误。

测试.java:7:无法访问的语句

我可以理解为什么警告可能被证明是有未使用的代码是不好的做法。但我不明白为什么这需要产生错误。

这仅仅是Java试图成为保姆,还是有充分的理由使这成为编译器错误?


答案 1

因为无法访问的代码对编译器毫无意义。虽然使代码对人们有意义既重要又比使代码对编译器有意义更难,但编译器是代码的基本消费者。Java的设计者认为,对编译器没有意义的代码就是一个错误。他们的立场是,如果你有一些无法访问的代码,你犯了一个需要修复的错误。

这里有一个类似的问题:无法访问的代码:错误还是警告?,其中作者说“我个人强烈认为它应该是一个错误:如果程序员写了一段代码,它应该总是打算在某些情况下实际运行它。显然,Java的语言设计者都同意这一点。

无法访问的代码是否应该阻止编译是一个永远不会达成共识的问题。但这就是Java设计者这样做的原因。


评论中的许多人指出,有许多类无法访问的代码Java不会阻止编译。如果我正确地理解了哥德尔的后果,那么任何编译器都不可能捕获所有无法到达的代码类。

单元测试无法捕获每个 bug。我们不会用这个作为反对它们价值的论据。同样,编译器无法捕获所有有问题的代码,但是对于它来说,在可能的情况下防止编译不良代码仍然很有价值。

Java 语言设计人员将无法访问的代码视为错误。因此,在可能的情况下阻止它编译是合理的。


(在你投反对票之前:问题不在于Java是否应该有一个无法访问的语句编译器错误。问题是为什么Java有一个无法访问的语句编译器错误。不要仅仅因为你认为Java做出了错误的设计决策就反对我。


答案 2

没有明确的理由说明为什么不能触及的语句必须被允许;其他语言允许他们没有问题。对于您的特定需求,这是通常的技巧:

if (true) return;

这看起来很荒谬,任何阅读代码的人都会猜测它一定是故意做的,而不是一个粗心大意的错误,让其余的语句无法访问。

Java对“条件编译”有一点支持

http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.21

if (false) { x=3; }

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

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

static final boolean DEBUG = false;

然后编写代码,例如:

if (DEBUG) { x=3; }

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


推荐