断点调试(debug)

断点调试(debug)

一个实际需求

  1. 在开发中, 新手程序员在查找错误时, 这时老程序员就会温馨提示, 可以用断点调试, 一步一步的看源码执行的过程,从而发现错误所在。

  2. 重要提示 : 在断点调试 过程中,是运行状态,是以对象的 运行类型 来执行的

 

断点调试介绍

  1. 断点调试是指在程序的某一行设置一个断点, 调试时,程序运行到这一行就会停住, 然后可以一步一步往下调试调试过程中可以看各个变量当前的值,出错的话 , 调试到出错的代码行即显示错误 ,停下 .进而分析从而找到这个BUG

  1. 断点调试是程序员必须掌握的技能。

  2. 断点调试也能帮助我们查看java底层源代码的执行过程,提高程序员的Java水平。

断点调试的快捷健:

F7(跳入) F8(跳过) shift + F8(跳出) F9(resume ,执行到下一个断点)

F7 : 跳入方法内

F8 : 逐行执行代码

shift + F8 :跳出方法

断点调试应用案例

 

 鼠标左击行的内容即可以在指定的位置下断点

 

 右键选择debug

案例 1

 com.edu.debug_ 包 Debug01.java

看一下变量的变化情况等

package com.edu.debug_;

public class Debug01 {
  public static void main(String[] args) {
      //演示逐行执行
      int sum = 0;
      for (int i = 0; i < 5; i++) {
          sum =+ i;
          System.out.println("sum="+sum);
      }
      System.out.println("退出了for循环");
  }
}

设置好断点之后 ,右键debug执行 之后 ,通过点击step over 可以实现逐行执行

当我们查看别人的代码 ,如果看不懂 ,可以通过debug的方法逐行执行 F8

案例 2

看一下数组越界的异常 Debug02.java

package com.edu.debug_;

public class Debug02 {
  public static void main(String[] args) {
      int[] arr = {1, 10, -1};
      for (int i = 0; i <= arr.length; i++) {
          System.out.println(arr[i]);
      }
      System.out.println("退出 for");
  }
}
 

 

 

通过debug的调试可以清楚的看到变量的值通过循环逐行执行不断地变化

 

 同时我们还可以将鼠标指针放到变量上面点击加号 ,查看变量的详细信息

 

 

 

当代码执行到这里可以看到出现了错误 : 发现了一个无效的数组范围

再次执行报错了 ,因此我们就可以发现原因是出现了超出了范围的错误

 

案例 3

演示如何追源码,看看 java 设计者是怎么实现的。(提高编程思想)。

小技巧:将光标放在某个变量上,可以看到最新的数据。 Debug03.java

package com.edu.debug_;
import java.util.Arrays;

public class Debug03 {
  public static void main(String[] args) {
      int[] arr = {1, -1, 10, -20, 100};
      //我们看看 Arrays.sort 方法底层实现.->Debug
      Arrays.sort(arr);
      for (int i = 0; i < arr.length; i++) {
          System.out.print(arr[i] + "\t");
      }

  }
}
 

 

 如果想要进入sort方法中可以输入快捷键F

 

 

 可以发现不但数组被排序完成 ,而且在上方的数组右边可以看到发生变化的数组元素 ,以一种特别的颜色注释显示了出来

而为什么F7没有进入这个方法 ,这个时候我们可以通过 force step into 或者 快捷键 alt+shift+F7

 

 

 可以看到成功进入到了目标的源码中去了

 另外一种解决方法就是通过配置的方式进行解决 

点击 Setting - > Build ,Execution ,Deployment -> Debugger -> Stepping 

将Do not step into the classes 中的java.* ,javax.* 取消勾选 , 其他的随意即可

 

 接下来F7就可以成功进入其源码了

也就是说 默认情况下是不让我们进入类中去的 ,因此我们需要自己去配置

此时进入到新的方法当中我们仍然还可以通过F7来继续深入到其中的方法中去

 

从这里进入之后

 

 可以看到内部的代码量十分之多 ,同时这是一个双组快排的算法

 而此时光标定位到了这个代码当中去之后 ,如果我们想要回到原来的主方法的时候 ,就可以一层层的再跳转回去

即 shift+F8跳出方法

 

 

 或者点击这里的step out

 

 当我们跳转回去的时候 ,可以看到sort方法已经执行完毕了 ,同时也可以继续逐行执行

这个过程有点类似递归

 

案例 4

演示如何直接执行到下一个断点 F9 resume。

小技巧: 断点可以在 debug 过程中,动态的下断点

package com.edu.debug_;
import java.util.Arrays;

//演示执行到下一个断点,同时支持动态的下断点.
public class Debug04 {
  public static void main(String[] args) {
      int[] arr = {1, -1, 10, -20, 100};
//我们看看 Arrays.sort 方法底层实现.->Debug
      Arrays.sort(arr);
      for (int i = 0; i < arr.length; i++) {
          System.out.print(arr[i] + "\t");
      }
      System.out.println("hello100");
      System.out.println("hello200");
      System.out.println("hello300");
      System.out.println("hello400");
      System.out.println("hello500");
      System.out.println("hello600");
      System.out.println("hello700");
  }
}
 

 

 在程序执行之前下两个断点

我们如果不想看中间执行的过程 直接看下一个断点的执行内容 就可以点击F9

 

 也就是这个位置

 

可以看到代码不仅跳转到了下一个断点 ,同时也将中间的循环数组也执行完毕了 

而如果我们想要直接执行到hello600的位置 ,那也是可以的 ,只需要在那一行代码上面下一个断点即可

 

 同时我们不仅可以给自己写的代码添加断点 ,同时也可以给系统的JDK源码下断点

 

 进入到系统的双轴快排源码中去

 

 这里通过下断点 ,直接跳转到了这一行的代码中去

这种技巧对以后的多线程开发是十分有用的 ,查看代码对应的业务逻辑就可以使用这个debug调试方法

 

断点调试练习

DebugExercise.java

  1. 使用断点调试的方法 ,追踪下一个对象的创建过程 ,Person[name,age,构造器...]

  1. 我们使用断点调试 ,查看动态绑定机制的如何工作

package com.edu.debug_;

//debug对象创建的过程,加深对调试的理解
public class DebugExercise {
  public static void main(String[] args) {
      //创建对象的流程
      //1.加载Person类信息
      //2.初始化 默认属性初始化 ,显式初始化 ,构造器初始化
      //3.返回对象的地址
      Person jack = new Person("jack",20);
      System.out.println(jack);
  }
}
class Person{
  private String name;
  private int age;

  public Person(String name, int age) {
      this.name = name;
      this.age = age;
  }

  @Override
  public String toString() {
      return "Person{" +
              "name='" + name + '\'' +
              ", age=" + age +
              '}';
  }
}
 首先通过调试可以得出第一步加载类信息

 进入到了类加载器中

 即加载这个类

 

 下一步就是进入到构造器中 ,对属性进行初始化操作

 

接下来执行到这个位置的时候 ,会调用到toString方法

 

 

 在 String s = String.valueOf(x); 这行调用到toString方法

 

obj是否为空 ,否则就调用 toString

 由于obj的运行类型是Person ,因此就会进入到Person的toString方法

此时s接收到了toString发过来的字符串

 

 到这里信息就输出出来了

 

 

  1. 我们使用断点调试 ,查看动态绑定机制的如何工作

找到我们之前学习多态的时候联系的代码 ,将这个代码

 step into到a.sum()上

 

 此时由于没有找到父类的sum方法 ,因此跳转到子类当中去

 

 

 

 

由于a对象的运行类型是B因此当调用getI方法的时候 ,会根据动态绑定机制 ,调用到子类的getI方法中去

 

posted @   comia  阅读(633)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示