带你走进Debug的世界(基于Eclipse、IntelliJ IDEA)

断了今生、忘了曾经 提交于 2020-03-05 18:36:15

关于Debug和本文

Debug,意为“调试”,是程序员必备技能之一。
想写Debug的文已经很久了,因为我刚学Java的时候也不会Debug,学校也不讲(我们那课叫面向对象程序设计基础,不是Java开发技术啥的),就没好好讲Debug,说是可以自己学啊或者使用System.out.println()啊,可惜我也一直没找到看得懂的东西。直到后来,做一个小型项目,我遇到了很多的NullPointerException,不得不自己琢磨Debug怎么用,顺便请教了一下老师和朋友,就基本学会了使用Debug。
Debug开始用的时候还是很不习惯的,但慢慢用久了,就很香了。
我呢,倒不想把本文写的很复杂,只是希望能给初学者一份导引吧。

对于某些“大佬”,你的技术固然尚可,但做人大可不必过于刻薄,感谢!

Debug的三种手段

  • 断点(breakpoint)
    • 打上断点以后,程序运行到断点处就会暂停,可以一步一步观察运行情况。
  • 跟踪(trace)
    • 跟着流程一步一步走,看看程序代码的执行流程。
    • 跟着流程一步一步走,看看变量动态的变化情况。
  • 监视(watch)
    • 即时监视:鼠标指向变量。
    • 快速监视:点右键,Inspector。
    • 添加监视:点右键,Watch。

IntelliJ IDEA

最简单的程序

先随着一个最简单的程序看IDEA的Debug流程。

我们选择一个1+2+…+10的程序,我们通过这个最基本的程序了解如何去Debug。
IDEA我个人比较喜欢用F8来逐行运行观察,发现问题再追踪。
在这里插入图片描述
在标注行数的左边栏的空白处,点一下,会出现一个红点,带出一条红线,这叫断点(IDEA的断点真的比Eclipse好看和便于增删)。

打断点的目的是使程序Debug运行到这里的时候会停住,我们能逐步地观察变量的变化、程序语句执行的流程等等。

根据我的观察,其实对于初学者,需要测试的部分中一个方法打一个断点就够了,因为一直按F8就会继续逐行执行,希望我这么说会比较容易接受一些。
在这里插入图片描述

右键Debug运行,注意不要Run,Run的话断点就无效了。
在这里插入图片描述

开始运行后,可以看出程序停在了打断点的那一行处,并且有很多灰色的k-v对,下方的Variable栏就会出现各种变量的值,可以追踪各个变量的当前值和值的变化。

按F8就可以继续执行。
在这里插入图片描述

Variable栏中蓝色的变量表示刚刚被修改过:
在这里插入图片描述
在这里插入图片描述

运行结束,得到结果:(事实上如果真有Bug,能发现的话在过程中就发现了)
在这里插入图片描述

不断的输入

我们可能需要命令行输入很多数据,有时候我们选择复制后一股脑输入Debug的Console中,但很多时候我们输入几个值并按回车就自动进入了Debug。而Debug运行到需要IO的地方就会阻塞,那么怎么去增加新的输入呢?

先输入10,然后回车:
在这里插入图片描述

程序跳到上面讲过的Debug界面:
在这里插入图片描述

顺着执行,会被IO卡住,那怎么办呢?点击Console,切到Console界面:
在这里插入图片描述

输入新的值,回车:
在这里插入图片描述
这次就不是自动切回去了,需要点击下方的Debugger:
在这里插入图片描述

程序继续执行:
在这里插入图片描述

Console识别在一次IO后就切Debugger,所以比较省事的做法是,第一次就把所有的数据输进去。

中断Debug

想中断Debug就和中断Run一样,左边栏的红色方框,点一下就能结束。

多方法打断点

下面的代码除了main()外还有一个多行的方法被调用,如果我们在for那里打上断点能不能进入function()呢?

public class PlusTest {

    private static int function(int num) {
        int sum = 0;
        for (int i = 1; i <= num; i++) {
            sum += i;
        }
        return sum;
    }

    public static void main(String[] args) {
        int sum = 0;
        int num = 10;
        for (int i = 1; i <= num; i++) {
            sum += function(i);
        }
        System.out.println(sum);
    }
    
}

从这个时候开始观测(只有这一个断点):
在这里插入图片描述
下一步:
在这里插入图片描述
下一步:
在这里插入图片描述

我们发现,并没进入function(),这怎么办呢?
当然是把function()也打上断点:
在这里插入图片描述

接着走下去:
在这里插入图片描述

下一步:
在这里插入图片描述

哇偶,进去了!我们可以在function()方法里继续观察变量的变化了。

递归函数的Debug

递归的话有明显的回溯感,特别是对于二叉树递归算法,要是打断点会感觉一会儿前进一会儿回溯。

要把握清楚到底在哪个子过程中递归,看准变量的变化。

这里也不拿很复杂的递归函数说事了,就说说阶乘递归函数吧:

public class PlusTest {

    private static int function(int num) {
        if (num == 0 || num == 1) {
            return 1;
        }
        return num * function(num-1);
    }

    public static void main(String[] args) {
        int num = 10;
        System.out.println(function(num));
    }

}

向下分解问题、递归:
在这里插入图片描述

递归到终止条件了:
在这里插入图片描述

到达递归终止条件后,就开始一步步弹出栈、形成答案了:
在这里插入图片描述

输出结果:
在这里插入图片描述

还是提一句,比如二叉树,在递归的时候不仔细可能不知道递归到哪里了,还是要仔细心些哇!

Eclipse

Eclipse太丑,我都不想说了,哈哈。

还是上面那个递归的例子吧,介绍一下Eclipse的Debug功能。

注意左边的小点,你明白我为什么批判Eclipse的断点比不上IDEA了吧,真的太low了……
我现在用Eclipse打断点一般都双击保证打上……

反正左边这个就是断点啦!

在这里插入图片描述

右键选择Debug运行:
在这里插入图片描述
会提示选择进入Debug的模式,一定要进去,点Switch:
在这里插入图片描述

左边有调用栈的信息,右边有变量表、断点表等信息,中间是代码,下面是Console:
在这里插入图片描述

这里提示全部的断点,不用的时候别忘了“拔了”,防止回头麻烦啊!
在这里插入图片描述

递归回溯的时候,左边调用栈瞩目:
在这里插入图片描述

按F6就像IDEA的F8一样啦,一行一行执行;而F5的话还能追溯调用栈找到源码,甚至可用来阅读源码

在这里插入图片描述

鼠标移到变量上还能直接看变量的值和状况:
在这里插入图片描述

右上角的小Bug图案,右键点击,选择Close即可退出Debug样式、返回普通模式:
在这里插入图片描述

Eclipse和NetBeans的Debug比较

功能描述 Eclipse NetBeans
逐语句执行 F5 F7
逐过程执行 F6 F8
跳出函数 F7 Ctrl+F7
运行到光标处 Ctrl+R F4
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!