Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
理解使用Eclipse的Java递归';调试器_Java_Eclipse_Debugging_Recursion - Fatal编程技术网

理解使用Eclipse的Java递归';调试器

理解使用Eclipse的Java递归';调试器,java,eclipse,debugging,recursion,Java,Eclipse,Debugging,Recursion,为了理解这个概念(我很难理解),我将在Java中进行一些简单的递归练习。到目前为止,我的所有研究都在很大程度上依赖于Eclipse的调试器,以便准确地理解我的代码在做什么。然而,当涉及到递归时,我发现情况并非如此,因为很难准确跟踪正在发生的事情 考虑到以下代码,返回nth Fibonacci数的方法: public int fibonacci(int n) { if (n == 0 || n == 1) { return n; } else { r

为了理解这个概念(我很难理解),我将在Java中进行一些简单的递归练习。到目前为止,我的所有研究都在很大程度上依赖于Eclipse的调试器,以便准确地理解我的代码在做什么。然而,当涉及到递归时,我发现情况并非如此,因为很难准确跟踪正在发生的事情

考虑到以下代码,返回
n
th Fibonacci数的方法:

public int fibonacci(int n) {
    if (n == 0 || n == 1) {
        return n;
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}
当使用此代码的调试器时,很难准确跟踪正在发生的事情以及在何处/何时发生的事情。只有一个变量,它每一步都会改变,并且,如果有一个小的
n
值,例如7,它已经变得很难跟踪,因为在最终达到13之前执行的步骤太多了

我想知道:

  • 如何更好地调试递归代码(通常),以便更好地理解递归
  • 考虑到
    返回fibonacci(n-1)+fibonacci(n-2)
    的概念很容易理解,我是否过于关注此类事情的调试

  • 您可以在打印
    n
    值及其
    fibonnacci
    值的每个指令中使用简单的
    System.out.prinln()
    对其进行调试

    下面是一个示例代码:

    public int fibonacci(int n) {
      if (n == 0 || n == 1) {
         System.out.println("your value is: " +n+ " and its Fibonacci value is: "+n);
         return n;
      } else {
        System.out.println("your value is: " +n+ " and its Fibonacci value is: "+fibonacci(n - 1) + fibonacci(n - 2));
        return fibonacci(n - 1) + fibonacci(n - 2);
      }
    }
    

    您可以测试

    我花了一段时间才掌握递归,出于这样或那样的原因,我从未发现调试器有用。我将尝试向您解释我是如何做的,并且它不涉及调试器(免责声明:这是一种个人方法,可能不正确或不通用)

  • 在递归代码中,始终至少有一个终止块和一个 递归块。将这两个部分分开

    返回n->端接块

    返回fibonacci(n-1)+fibonacci(n-2)->递归块

  • 递归块表示递归的抽象规则。使用相同的函数获取这些值,而不是将这些值放在变量
    Fn1
    Fn2
    中。考虑砖墙:递归函数创建墙,将砖块添加到现有墙中。在递归块内部,在某一步,您不在乎是谁以及如何创建了现有墙,只需向其中添加一块新砖即可。然后,墙是由相同的功能创建的,一次一块砖

  • 在终止块处,使用一些值调用代码。在流程结束时,该值会发生什么变化?说到斐波那契,在过程的最后(
    n=1
    n=0
    ),我必须再次将这些数字加到总数中。这是由递归块完成的。换句话说,终止块向递归块提供具体的值(而不是如何获得它们的过程)

  • 当我必须进行故障排除时,我会在每一步打印值,这是我找到的最好的解决方案。然后我检查他们是否是他们应该是的。对于您的斐波那契,我希望看到这样的输出

    代码:

    输出:

    Input value: 4
    Recursion block value: fibonacci(3) + fibonacci(2)
    
    Input value: 3
    Recursion block value: fibonacci(2) + fibonacci(1)
    
    Input value: 2
    Recursion block value: fibonacci(1) + fibonacci(0)
    
    Input value: 1
    Terminating block value: 1
    
    Input value: 0
    Terminating block value: 0
    Recursion block return value: 1
    
    Input value: 1
    Terminating block value: 1
    Recursion block return value: 2
    
    Input value: 2
    Recursion block value: fibonacci(1) + fibonacci(0)
    
    Input value: 1
    Terminating block value: 1
    
    Input value: 0
    Terminating block value: 0
    Recursion block return value: 1
    Recursion block return value: 3
    
    您还可以阅读一些有用的内容,这些内容与递归密切相关。

    如何调试递归代码? 首先,确保已切换到“调试”透视图,并且看到了正确的窗口(
    变量
    表达式
    调试
    和源代码),例如:

    接下来,请注意,在
    Debug
    中,您可以看到当前调用该方法的频率。此列表将根据调用了多少方法以及尚未返回多少方法而增减

    您可以单击其中一个方法来更改范围。查看更改范围时
    变量的内容如何更改

    最后,要检查任意内容,请在
    expressions
    窗口中输入表达式。这几乎就像是实时编码。你几乎可以检查任何东西

    我是否过于关注调试? 不。学会正确地做这件事,以后会节省你很多时间

    添加一个
    System.out.println()
    需要重新编译,您需要重现并不总是那么简单的情况。

    内联代码使得使用Eclipse调试器更加困难,因为它非常注重显示不存在的局部变量。通过使事情更加详细并保存到变量中,可以更容易地逐步完成。通过这种方式,您可以更容易地看到正在发生的事情和结果。例如,按以下方式修改代码将使在上使用调试器更容易:

    public int fibonacci(int n) {
        if (n == 0 || n == 1) {
            return n;
        } else {
            int nMinus1 = fibonacci(n - 1);
            int nMinus2 = fibonacci(n - 2);
            int retValue = nMinus1 + nMinus2;
            return retValue;
        }
    }
    

    免责声明:我没有尝试编译此代码。

    您是否尝试在一张纸上绘制调用结构?这可能是理解递归正在做什么的一个很好的练习IMHO@RC:请不要通过打印到系统输出来教他进行调试。我知道有太多的开发人员正是这样做的,这通常会使其成为生产代码。++用于尝试理解递归和调试器。您可能需要仔细查看调用堆栈。Eclipse允许您选择堆栈框架并查看该堆栈框架中的变量值。这有助于理解递归。
    public int fibonacci(int n) {
        if (n == 0 || n == 1) {
            return n;
        } else {
            int nMinus1 = fibonacci(n - 1);
            int nMinus2 = fibonacci(n - 2);
            int retValue = nMinus1 + nMinus2;
            return retValue;
        }
    }