在工作中看到很多水平不错的程序员,在调试代码的时候,也还只是停留在单步 debug 的阶段。如果能掌握更多的代码调试技巧,那么将大大提升工作效率。下面就让我么一起来系统的学习下 IDEA 的调试技巧吧。
默认设置下,idea 用 debug 模式启动项目时,会自动进入弹出 debug 界面,下面是 debug 窗口的各个工作区的介绍:
1 调试按钮:总共有 8 个按钮,对应着相应的执行动作。鼠标悬停可以看到对应的快捷键,或者在菜单栏 run 里面也能看到对应的快捷键
2 服务按钮:可以在这里重启/关闭程序,设置断点等。
3 方法调用栈:显示该线程调试时所执行的所有方法,最早调用的方法显示在最底部。
4 Variables:显示当前方法体内,断点之前的所有变量(即已经执行过的语句的变量)。
5 Watches:查看变量,可在该窗口查看变量的值。
下面对每组工作区的用法做一个详细介绍
从调试按钮说起,共 8 个按钮,从左到右依次讲解
服务按钮共 6 个,从上到下依此讲解
在 debug 过程中,跟踪查看变量的值是非常有必要的,在 idea 中有几个地方能查看变量的值
点击 "+" 能看到变量的详细信息
回车可看到变量的详细信息如下:
计算表达式的功能是非常强大的。当你需要查看某个表达式的值的时候,或者需要修改变量的值的时候就可以用计算表达式。
当我们需要查看某个表达式的结果时,可以选中某个表达式,然后再按 Alt + F8,弹出计算表达式窗口,再按回车或者点击下方的 Evaluate 按钮计算表达式的值
计算表达式也可以修改计算表达式的值,这样我们不需要重新修改代码或者设置改参数重新请求就能很方便的测试程序的各种情况
当一行代码有几个方法的时候,用之前的步入功能(F7)怎么知道步入的是哪个方法呢,这时候就需要智能步入了,按Shift + F7,会自动列出该断点行的所有方法,选中需要步入的方法,就能步入到该方法中
session.setAttribute(Const.CURRENT_USER,response.getData()) 这句代码包含了 getData() 和 setAttribute() 方法,按 Alt + F7 会显示两个方法,单击需要步入的方法即可
假设我们的代码中遍历一个 size 为100的 List,在遍历到第88次抛异常了,这时候,我们要 debug,如果我们在循环内设置一个断点,然后一直按 F9,直到第88次循环为止那岂不是既 low 又费时。idea 的 debug 功能已经为我们考虑到了该场景,在断点上点击右键,在 Condition 后面的输入框设置断点的条件,只有在条件成立的时候,断点才生效
点击 View Points,弹出 BreakPoints 窗口,能查看所有断点并设置断点
Java Line Breakpoints ——我们设置的断点
Java Exception BreakPoints ——异常断点
JavaScript Exception BreakPoints ——js异常断点
Enable ——设置断点是否禁用
Condition ——断点条件
Suppend ——断点类型
当我们需要拦截程序异常的时候,可以在 Java Exception BreakPoints 添加一个异常断点,当程序抛指定异常的时候,自动定位到该异常行
如下面代码执行的时候会抛出一个 ArithmeticException 异常,这时候我们并没有设置断点
@Test
public void test() {
//该代码会抛出 ArithmeticException 异常
int a = 100 / 0;
}
打开View Points窗口,添加异常断点
执行程序,程序会在执行到 int a = 100/0;的位置进入进入断点。
话不多说,先看下面代码
这里我们在 main 方法中启动了 3 个线程,在 MyRunnable 的 run 方法中打了断点,这时候,当我们调试 main 的时候,程序进入断点。(我这里显示的是进入到线程 2 的断点,实际情况可能是线程 1 或 3 ),然后按 F8 执行下一步,这时候线程的方法体执行完毕,我们看到客户端打印了 3 条日志
15:05:31.400 [线程3] INFO com.huang.mmall.Main - 我是线程:线程3
15:05:31.400 [线程1] INFO com.huang.mmall.Main - 我是线程:线程1
15:05:31.400 [线程2] INFO com.huang.mmall.Main - 我是线程:线程2
奇怪了,我们明明只 debug 了一个线程,为什么三个线程都执行完了呢,这是由于 idea 在 debug 时的默认阻塞级别是 All,会阻塞其余线程,当我们的线程执行完毕才执行其他线程。当我们需要多线程调试的时候,只需修改断点的阻塞级别为 Thread 即可
这时候重新执行 debug,会看到三个线程同时进入了 debug,这时候,我们可以随意切换线程,控制线程的执行顺序
这时候切换到线程 1,然后按两次 F8 是线程执行完毕,看到控制台输出"我是线程:线程1",并不会像上面一样其他线程的日志也输出,只有在执行到该线程的代码的时候才输出。
断点回退其实就是回退到该代码所在方法的调用处,idea debug 模式无法一步步回退到上一句代码或者上个断点,只能回退到上个方法。需要注意的是断点回退只能重新走下流程,变量/数据的状态已经改变了是无法回退的。例如数据库插入等操作
也可以在方法调用栈中,选择要回退的方法,然后右键 Drop Frame
以前当我不想继续执行剩下的流程的时候(可能涉及到数据库的插入操作),我都是直接停止程序,然后重新启动。当其实可以有更巧妙的方法,可以利用 Force Return 强制返回结果,不执行剩下的代码。
在方法栈中选中想要中断的方法,然后右键,选择 Force Return
这里会弹出一个弹窗让你填写返回值,我直接返回 null
参考资料:https://www.cnblogs.com/chiangchou/p/idea-debug.html
扫码关注我,一起学习,一起进步