【问题标题】:Missing return statement for if/else statement缺少 if/else 语句的返回语句
【发布时间】:2023-02-21 13:19:55
【问题描述】:
public int checkGuess(int g, int randomnumber){

    number=g;
    this.randomnumber= randomnumber;

    if (number == randomnumber)
        return 0;

    else if (number < randomnumber)
        return -1;

    else if (number > randomnumber)
        return 1;

}

为什么这会给我一个缺少的返回语句错误?每个 if/else 都有一个回报 最后一个括号出现错误

【问题讨论】:

  • 应在else 内或整个if/else-ifs 外进行退货
  • 因为您缺少隐含的 else 的 return 语句。

标签: java


【解决方案1】:

每个return 语句都在if 语句中。虽然这在逻辑上可能是不可能的,但编译器需要在 if 都不为真时返回。

我建议:

public int checkGuess(int number, int randomnumber){
    int retVal = 0;
    this.randomnumber= randomnumber;

    if (number == randomnumber) {
        retVal = 0;
    } else if (number < randomnumber) {
        retVal = -1;
    } else if (number > randomnumber) {
        retVal = 1;
    }
    return retVal;
}

在我看来,此解决方案修复了编译器问题并略微提高了可读性。


或者,有这个解决方案:

public int checkGuess(int number, int randomnumber){
    this.randomnumber= randomnumber;

    if (number == randomnumber) {
        return 0;
    } else if (number < randomnumber) {
        return -1;
    } else if (number > randomnumber) {
        return 1;
    } else {
        //throw an exception
    }
}    

抛出异常将允许您在不返回任何内容的情况下退出该方法……因为可以说,如果您到达最后的else,显然出了问题。

【讨论】:

  • +1 建议抛出异常,当您确信代码无法访问时,这确实是最好的做法。
  • 如果您认为该方法不应该接受不满足定义条件之一的价值,那么对我来说,+1 投掷 IllegalArgumentException 是最好的。
  • 仅仅因为编译器不能弄清楚只有三种可能性并不意味着程序员不能
  • 而且不管程序员是否已经弄清楚了这一点,编译器才是最重要的……他是编译你的代码的那个。
【解决方案2】:

您可以尝试将 las else if 更改为 else

if (number == randomnumber)
    return 0;

else if (number < randomnumber)
    return -1;

else
    return 1;

【讨论】:

  • 是的,我知道这行得通,但我认为不是说如果数字更大则返回 1;弄乱了测试文件。有什么方法可以保持这种状态吗?
【解决方案3】:

编译器不需要能够确定您的 if/else 树是否涵盖了所有可能的情况。如果您编写的代码让一些编译器足够聪明,可以判断出是正确的,而其他编译器则不是,那就太糟糕了。 Java 并没有对编译器的智能程度有一个精确的规范,而是要求您编写清晰、干净的代码。

根据 Java 规范中的定义,函数的右大括号是可访问的。您可以通过其他“可达”定义来证明它无法到达并不重要。 “可达”的 Java 规范概念是编译器可以实际实现的规范中详细解释的正式概念。这不是“可达”的常识性概念,无论如何都无法教给计算机。

【讨论】:

    【解决方案4】:

    基本上,编译器不够聪明,无法意识到 number == randomnumber || number &lt; randomnumber || number &gt; randomnumber 是重言式。由于您没有else,它认为您可能会通过条件,然后在不返回的情况下到达函数末尾。最简单的解决方法是将最后一个 elseif 更改为 else。您从前面的条件中知道,如果达到该点,number &gt; randomnumber 必须为真。 (如果你偏执并想确定,你可以添加一个断言。)

    【讨论】:

      【解决方案5】:

      return 语句之后不需要 else

      if (number == randomnumber)
        return 0;
      
      if (number < randomnumber)
        return -1;
      
      // Must be true: if (number > randomnumber)
      return 1;
      

      请注意,这解决了问题的原因是因为编译器不检查逻辑上必须返回的解决方案。例如虽然 A 必须 > < 或 = 到 B,但它不会检查该关系。它正在寻找明确涵盖每条路径的可能性。

      【讨论】:

      • 虽然返回后的 else 不是必需的,但它有助于提高可读性(尤其是在 if 正文不仅仅是简单的 return 0; 的情况下。但是无论哪种方式,该部分都与实际问题无关(尽管您的发布的代码确实解决了问题......只是没有解释问题,留下了误导性的答案)。
      • @nhgrif 添加注释来解释原因,{} 也使这一点更清楚,有或没有其他。我添加它们并不是为了突出我所呈现的差异。
      • @nhgrif 我相信当在 IF-return 语句之后不使用 ELSE 时,代码更具可读性和逻辑性。
      【解决方案6】:

      您需要一个 else 才能按预期工作,它不会评估您的条件以知道它总是会返回

      【讨论】:

        【解决方案7】:

        应在else 内或整个if/else-if 外进行退货。根据条件,所有退货都可能永远不会退货

        if (condition 1)
            return a;
        else if (condition 2)
            return b;
        else if (condition 3)
            return c;
        

        如果条件 1、2 或 3 都不满足,则不会返回。应始终提供退货。所以修复方法是:

        if (condition 1)
            return a;
        else if (condition 2)
            return b;
        else if (condition 3)
            return c;
        else
            return d;
        

        或者

        if (condition 1)
            return a;
        else if (condition 2)
            return b;
        else if (condition 3)
            return c
        
        return d;
        

        【讨论】:

          【解决方案8】:

          Java 要求保证非 void 方法返回某些东西(即使它是 null)。如果有 if 语句,根据定义,只有有时你的 return 语句才会运行。

          if(number == randomnumber) {
              return 0;
          } else if(number < randomnumber) {
              return -1;
          } else if(number > randomnumber) {
              return 1;
          } else {
              return -2;
          }
          

          else 语句不是必需的,但它确实使 imo 更容易理解。

          【讨论】:

          • 在我看来,else return -2; 在这里非常草率,并且妨碍了可读性。这个答案确实解决了编译器问题。