Java 无编译错误的无限循环中断方法签名

Java 无编译错误的无限循环中断方法签名,java,compilation,infinite-loop,Java,Compilation,Infinite Loop,我想知道为什么Java中允许使用以下代码,而不会出现编译错误? 在我看来,这段代码通过不返回任何字符串来破坏方法签名。 有人能解释一下我遗漏了什么吗 public class Loop { private String withoutReturnStatement() { while(true) {} } public static void main(String[] a) { new Loop().withoutReturnStatement(); } }

我想知道为什么Java中允许使用以下代码,而不会出现编译错误? 在我看来,这段代码通过不返回任何字符串来破坏方法签名。 有人能解释一下我遗漏了什么吗

public class Loop {

  private String withoutReturnStatement() {
    while(true) {}
  }

  public static void main(String[] a) {
    new Loop().withoutReturnStatement();
  }
}
方法的最后一个}是不可访问的-只有在不返回值的情况下可以到达方法的末尾时,才会出现编译错误

这对于由于异常而无法访问方法结尾的情况更有用,例如

private String find(int minLength) {
    for (String string : strings) {
        if (string.length() >= minLength) {
            return string;
        }
    }
    throw new SomeExceptionIndicatingTheProblem("...");
}
这方面的规则如下所示:

如果一个方法被声明为具有返回类型§8.4.5,那么如果该方法的主体能够正常完成§14.1,则会发生编译时错误

您的方法无法正常完成,因此没有错误。重要的是,不仅仅是它不能正常完成,规范也承认它不能正常完成。发件人:

如果以下至少一项为真,则while语句可以正常完成:

while语句是可访问的,条件表达式不是值为true的常量表达式§15.28。 有一个可到达的break语句退出while语句。 在您的例子中,条件表达式是一个值为true的常量,并且没有任何可访问的break语句,否则while语句无法正常完成

 private String withoutReturnStatement() {
    while(true) {
        // you will never come out from this loop
     } // so there will be no return value needed
    // never reach here ===> compiler not expecting a return value
  }  
要了解更多信息,请尝试以下方法

private String withoutReturnStatement() {
    while(true) {}
    return ""; // unreachable
}

它说的是不可访问语句

,因为编译器比您想象的更聪明,并且看到函数不会返回?这不仅是一个有趣的问题,也是一个热门的网络问题:D@sᴜʀᴇsʜᴀᴛᴛᴀ: Jon Skeet回答了这个问题…很好的问题…令我惊讶的是,这对cWelle@JonSkeet来说也是如此,尽管他的回答很好,我认为它没有强调基本点:方法签名中的返回类型并不是一个承诺,即方法最终将返回该类型的对象。由于停止问题的不可计算性,编译器无法验证这种承诺,而是一个承诺,如果方法返回,返回的值将是该类型。如果在回答的第二部分还指向JLS.+1,则会更有用。这非常清楚,抛出异常是有意义的。令人惊讶的是,当真的有价值时。特别是来自一种甚至不会编译的语言,它知道存在无法访问的代码。@PaulDraper:我不知道你的意思。在无限循环和异常这两种情况下,您通常无法到达方法的末尾,因此不需要返回。这样说吧-如果你在结尾有一个return语句,那将是不可访问的。。。不太好,我应该更清楚。答案是100%正确的,而1{}符合您引用的JLS。我只是很惊讶,他们选择这样设计,而实现者选择检查while循环的条件。这是一个停滞不前的问题,一场失败的战斗。while1{}编译,但whilefoo.length>0{}不编译,至少在OpenJDK 7中是这样。现在,另一个Java编译器可以选择更复杂的方式来识别这种情况。突然,你的“一次编写,随处运行”的代码被破坏了。@PaulDraper:不,编译器不能选择更复杂的。语言规范对可达性非常清楚。如果以下至少一项为真,则while语句可以正常完成:while语句是可访问的,且条件表达式不是值为真的常量表达式§15.28。[...]. foo.length>0不是常量表达式。Java并没有试图解决停顿问题——它只是定义了一些编译器必须遵守的明确规则,这些规则解决了编译时结果肯定是已知的少数情况。@StephenChung:请注意,术语常量表达式是由JLS定义的,因此要求每个符合条件的编译器都有相同的行为。例如bool foo=true;而foo{}需要一个return语句,因为foo没有引用JLS指定的常量表达式。然而,最终bool foo=真;whilefoo{}不允许返回,因为在本例中foo是一个常量表达式。