【问题标题】:How to correctly place a return statement in a recursive method with if\else conditions如何在具有 if\else 条件的递归方法中正确放置 return 语句
【发布时间】:2016-05-21 12:26:57
【问题描述】:

我正在编写使用 if\else 控制返回语句构建的递归代码。但是,当我编译时,我得到一个“缺少返回语句”,因为我所有的返回都在条件中。我正在添加“假”退货(该方法永远不会到达该退货),但我想知道是否有更智能的解决方案。

例如:

    private static boolean compare(int[][] a, int i) {
     if (i == a.length - 1) {
      return true;
     } 
     else {
       if (calcLineSum(a[i], 0, 0) == calcLineSum(a[i + 1], 0, 0)){
         compare(a, i + 1);
       }
       else { 
        return false;
       }
     }
     return false; //<= = 'fake'
    }
    private static int calcLineSum(int[] a, int i, int sum) {
     if (i == a.length)
      return sum;
     else {
      sum = sum + a[i];
      calcLineSum(a, i + 1, sum);
     }
     return sum; //<= = 'fake'
    }

非常感谢您的意见!

【问题讨论】:

  • 1) 格式化您的代码。 2)格式化你的代码。 3) 如果代码不应该到达那里 - 抛出异常。
  • 是什么让您认为您的代码永远不会达到这些回报?它绝对会。 return 仅退出该方法的 一个 调用,而不是整个递归堆栈。
  • 不只是格式化,而是在else 语句而不是if 语句上使用大括号让我畏缩。

标签: java recursion return


【解决方案1】:

我认为如果您将 compare(a,i+1); 替换为 return compare(a,i+1); 并将 calcLineSum(a,i+1,sum); 替换为 return calcLineSum(a,i+1,sum); 它应该可以编译。

每个ifelse if 都应该以return 结束。

【讨论】:

  • 谢谢你,这是一个非常有用的建议!您能否详细说明发生了什么以及再次调用该方法与进行返回语句之间有什么区别?谢谢!
  • @roony 就是这样。调用该方法并 - 忽略它所做的事情。另一个返回它。
【解决方案2】:

首先;正确缩进您的代码并为所有条件添加大括号。它将大大节省您数小时的调试时间。

当其格式正确时,很容易发现错误:

private static boolean compare (int[][]a, int i)
{
    if(i==a.length-1)
    {
        return true;
    }
    else
    {
        if(calcLineSum(a[i],0,0)==calcLineSum(a[i+1],0,0))
        {
            compare(a,i+1);
        }
        else 
        {
            return false;
        }
    }
    return false; <=='fake' return
}

您可以清楚地看到声明compare(a,i+1); 缺少return。调试愉快!

【讨论】:

    【解决方案3】:

    您似乎误解了return。在你的代码中

    private static int calcLineSum (int[]a, int i, int sum)
    {
        if(i==a.length)
            return sum; // only returns `sum` from this one invocation,
                        // *not* further up the recursive chain
        else {
            sum=sum+a[i];
            calcLineSum(a,i+1,sum);
            // your code is **still going** here; the `return` from
            // the recursive call didn't change anything
            // also note that `sum` hasn't actually changed here
            // sum is passed by value, and changes to it inside the recursive call
            // don't actually make any difference out here
        }
        return sum; // actually used
    }
    

    看起来正确的实现应该是

    private static int calcLineSum(int[] a, int i, int sum) {
      if (i == a.length) {
        return sum;
      } else {
        return calcLineSum(a, i+1, sum + a[i]);
      }
    }
    

    【讨论】:

    • 感谢您的详细解释。澄清一下:当我对方法调用本身进行返回时,一旦“返回”它也会终止所有其他调用?我注意到这是调试中发生的事情,但我希望了解其中的逻辑。再次感谢!
    • @roony:澄清一下:这正是不会发生的事情。它不会终止所有其他调用。在调试器中,它可能看起来像这样,因为它会立即在此之上执行另一个返回。
    • 所以基本上所有以前的调用都返回最后一次调用的值——到达基本情况并结束递归的那个?
    • 是的,只要你真的在那里放了一个回报。如果你不在那里放一个 return,它就不会返回下一级递归的值。
    【解决方案4】:

    试试这个方法:

    private static boolean compare (int[][]a, int i) {
        boolean result = false;
    
        if (i == a.length-1) {
            result = true;
        } else {
            if(calcLineSum(a[i],0,0) == calcLineSum(a[i+1],0,0)) {
                    result = compare(a,i+1);
            }
        }
    
        return result;
    }
    
    private static int calcLineSum (int[]a, int i, int sum) {
        int result = sum;
    
        if (i != a.length) {
            result = calcLineSum(a,i+1,sum+a[i]);
        }
    
        return result;
    }
    

    【讨论】:

      【解决方案5】:

      这里的问题是具有非void 返回类型的方法必须保证返回该类型的值。

      忽略具体代码,你的 compare 方法的结构基本上是:

      if() {
          return
      } else {
          if () {
              // you don't return anything here, 
              // so the method might not do what you promised it would,
              // namely return a value
          } else {
              return
          }
      }
      

      如果有任何方法可以运行但不会返回值,编译器会调用它。

      【讨论】:

        【解决方案6】:

        你的递归:

        private static int calcLineSum (int[]a, int i, int sum)
        {
            if(i==a.length)
                return sum;
            else {
                     sum=sum+a[i];
                     calcLineSum(a,i+1,sum);
                 }
            return sum; //<=='fake' return
        }
        

        你可以像这样做得很好:

        private static int calcLineSum (int[]a, int i, int sum)
        {
            if(i==a.length)
                return sum;
            sum=sum+a[i];
            calcLineSum(a,i+1,sum);
        }
        

        我所做的只是删除else。如果第一个条件不满足,不管有没有else,你都会执行这两行:

        sum=sum+a[i];
        calcLineSum(a,i+1,sum);
        

        它也简化了您的代码。

        另外,还可以去掉线

        sum=sum+a[i];
        

        这样写:

        private static int calcLineSum (int[]a, int i, int sum)
        {
            if(i==a.length)
                return sum;
            calcLineSum(a,i+1,sum+a[i]);
        }
        

        【讨论】:

          【解决方案7】:

          没有你最后的退货声明(你称之为假的);确实有条件不返回任何东西;

          例如,在您的第一个方法中,如果满足以下条件,则不会返回任何内容:

          if (calcLineSum(a[i], 0, 0) == calcLineSum(a[i + 1], 0, 0))
          

          同样,对于您的第二种方法,您的 else 块不会返回任何内容。

          作为一种良好的编码习惯,请使用 { } 包围 if 和 else 块。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-02-05
            • 2018-09-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多