java进阶路线——Debug
“每个大程序里都有一个不安分的小程序”,想要成为一名好的开发人员,你得先真正学会 Debug 才行"
1、什么是debug
是一个程序调试工具
①排除故障,排除错误
②调整程序,移去程序中的错误
2、为什么debug
(1) 现实
调试的真正问题在于无法规划所需的时间。所有编程活动,从设计到开发都可以有时间规划。但调试却完全不同,调试可能会花费一个小时、一天、甚至不知不觉一周就过去了,却还是未能发现问题的根源并修复问题
(2) 调试定律
1、理清思绪
先理解系统业务逻辑,再理解出现的问题
如果不理解这个系统的工作原理,那么就无法调试这个问题。一旦明白了系统以后,问题就很明显了。
2、分而治之
解决问题的关键在于缩小搜索范围
大型系统都很复杂,系统的运行涉及许多因素。从整体上来看系统,你很难区分出影响特定问题的细节。
解决方法是分而治之。不要着急着眼于整个系统,将有问题的组件或模块从代码中分离出来,才能进行严谨的调试。
分离问题有许多优点。你可以只关注与问题相关的部分,由于代码量很少,所以你可以快速解决问题。
请时刻牢记,通过剥丝抽茧,逐步缩小范围,最终 bug 将无藏身之。
3、单次改动
一次只做一个改动
如果你手中拿的是一把好步枪,那么你可以更好地修复 bug。
有些开发人员试图通过交换或修改其他组件来修复错误的代码。可能在他们改动了三四处代码后,发现可以正常工作了。这看似很酷,但是他们完全不知道哪个部分有问题。更糟糕的是,他们所做的这些改动很有可能破坏本来运行得好好的代码。
在很多情况下,你需要改动系统的不同部分,来看看是否对这个问题有影响。一般来说,这是一个警告,你并没有充分地了解代码,而是在猜测。你只是在改变问题发生的条件,而不是寻找问题自然发生的原因。
这种做法会隐藏第一个问题的原因,还会导致更多问题的发生。这是开发人员都需要避免的错觉陷阱。
请时刻牢记,
如果一次只做一个改动,那么你可以确切地知道哪个参数有效。如果改动看似没有效果,那么请立即恢复原样!
4、检查确认
这是一个黄金法则: 检查是否由于你的改动修复了bug,如果不是,那这个bug就没有修复
每个人都愿意相信 bug 不药而愈了——“似乎我们无法再重现这个 bug”——“这个 bug 出现了几次,但后来不知道发生了什么,不再重现了。”当然,合乎逻辑的结论是,“也许这个 bug 不会再发生。”但是,你猜怎么着?它还会发生。
如果你觉得你已经修复了某个 bug,那么你需要确保去掉你的改动后,这个 bug 会再次重现;还要确保加上改动后,bug 就会被修复。你需要重复从改好到重现再到改好的过程,只改动与修复 bug 有关的代码,否则就不能证明你修复了这个 bug。
修复 bug 往往很有意思。有时 bug 只是“隐藏了起来”而不是真正被解决了。有时候,当我们意识到我们的改动与要修复的 bug 无关时,产品早已发给了客户,显然他们不会满意这种产品。所以,千万不要掉入这样的陷阱中。
如果去掉你改动的代码,那么系统就会重现之前的 bug,只有这样才能确保你的修改确实有效
5、记录过程
将解决过程及办法以博客的方式记录,方便回顾
不要在同一个地方跌倒两次。为了提高工作效率,请记录所遇到的问题以及最终的解决方案。遇到问题时,我们不必再说:“我以前见过这个问题,但我不知道怎么解决。”你可以快速查找过去使用过的解决方案。不用说,这种做法不仅可以节省你的时间,还可以大大地提高你的自尊和自信。
3、怎么去debug
idea的debug模式,基本面板:
- 开启 Debug 模式的开关:通常在写代码时都会改用 Debug 模式来跑程序,已经很少使用旁边的 Run 模式了
- 设置断点:在左边行号栏单击左键就可以设置断点,再点一下则可以取消此断点,能够设置断点是 Debug 模式和 Run 模式最大的区别,而设置断点可以帮助我们对代码进行一步步的排查,这也是为什么推荐使用 Debug 模式而不是使用 Run 模式
- 调试按钮:Debug 调试代码的主要功能就对应着这几个按钮
- 服务按纽:和 Debug 的断点有关系,主要搭配着上一步一起用
- 变量区:可以查看当前断点之前的变量
4、基本用法
主要对应调试按钮和服务按钮,现在介绍一下每个按钮的名称及作用:
(1)调试按钮
从左向右:
- Show Execution Point : 如果你的光标在其它行或其它页面,点击这个按钮可跳转到当前代码执行的地方
- Step Over : 一行一行的代码往下执行,如果这一行上有方法不会进入方法
- Step Into : 如果当前行有方法,可以进入方法内部,一般用于进入自定义方法内,不会进入官方类库的方法
- Force Step Into : 强制进入方法内部,能进入任何方法,查看底层源码的时候可以用这个进入官方类库的方法
- Step Out : 退出方法,从进入的方法内退出到方法调用处,此时方法已执行完毕,只是还没有完成赋值
- Drop Frame : 回退断点,很少用到
- Run to Cursor : 运行到光标处,你可以将光标定位到你需要查看的那一行,然后使用这个功能,代码会运行至光标行,而不需要打断点(前提是已经进入了 Debug 模式,也就是已经停在某个断点上了)
- Evaluate Expression : 计算表达式,后面详细说明
(2)服务按钮
从上往下:
- Rerun : 重新运行程序,他会关闭服务后重新啓动程序,不过很少用到,通常都会直接关掉再开启一次
- Update ‘tech’ application : 更新程序,就是执行当初定义的 update 选项,当 Debug 模式启动后,再次点击 debug 按钮也会跳出此选项
- Resume Program : 继续执行程序,例如在第 20 行和 25 行有两个断点,而当前运行至第 20 行,按一下,则运行到下一个断点(即第 25 行),再按一下,则运行完整个流程,因爲后面已经没有断点了
- Pause Program : 暂停程序,很少用不是很重要
- Stop : 连续按两下关闭程序,有时候你会发现关闭服务再启动时,报端口被占有,这是因爲没完全关闭服务的原因
- View Breakpoints : 查看所有断点,后面第七部分详细说明
- Mute Breakpoints : 将所有断点变为灰色使断点失效,按 Resume Program 那个键(也就是第三个按键)可以直接运行完程序(因为所有打的断点都被设置为无效了),再次点击这个 Mute Breakpoints 按键可以使所有无效断点变为红色有效
(3)变量查看
- 参数所在行后面会显示当前变量的值
- 游标停到参数上,会显示当前变量信息,点击打开可以看到变量的详情
- 在下方的 Variables 变量区窗口查看,这里会显示当前方法的所有变量,可以一次看到所有变量的详情
(4) 计算表达式 Evaluate Expression
上面有提到一个计算表达式 Evaluation Expression 按钮,可以使用这个按钮在调试过程中计算某个表达式的值,或是直接改变某个变量的值,而不用再去重新改代码手动改变量的值然后再重启程序。
如果只是单纯想要改变变量的值的话,还有另一种方法,不用透过计算表达式那么麻烦。只要在 Variables 变量区直接在变量上点右键,使用 setValue 也能重新改变此变量的值的
(5)断点条件设置
有的时候在遍历一个集合或是数组的时候,可能只想要看 for 循环里的某个 i 值超过多少以上的变量情况,这时候就可以透过设置断点条件来达成,也就是说,只有在满足了断点条件时,才会停在断点处,不然就会直接忽略此断点。
对断点点击右键可以设置断点条件,像是下图是设置成在 i=3 时才停下(如果没有设置断点条件的话,则每进一次for loop,每个 i 都会停一次断点)
(6)查看所有断点
在左下方点击 View Breakpoints 可以查看目前已经设置的所有断点,有时候自己断点打多了很容易忘记打在哪,可以透过这个功能知道自己都在哪些地方打了断点,取消勾选可以使此断点失效
(7) 设置异常断点
当设置异常断点,在程序中出现需要拦截的异常时,会自动定位到异常行
设置方式一样是先点击 view breakpoints,之后点击 + 号添加异常断点,这边添加了 NullPointerException
当出现空指针异常时,会自动跳到抛出空指针异常的行数,省的我们再去定位问题点在哪,非常方便