目录
应用场景
重要提示
定义
快捷键
运行图
案例1
案例2
案例3
案例4
练习题
第一题
题目
代码
toString方法
第二题
题目
应用场景
查找错误时,用断点调试一步一步的看源码执行的过程,从而发现错误所在
重要提示
在断点调试(Debug)过程中,是运行状态,是以对象的运行类型来执行的
断点调式(Debug)过程中,是运行状态,是以对象的运行类型来执行的
eg :A extends B;B b = new A();b.xx();在调试时看运行类型A
定义
断点调试是指在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后程序员可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下,进行分析从而找到这个Bug,又叫Debug。
可以查看到java底层源代码的执行过程,提高程序员的Java水平
快捷键
| F7(跳入)跳入方法体内执行 F8(跳过)逐行执行代码. | shift+F8(跳出) :跳出方法 F9(resume,执行到下一个断点) | 
运行图
和老师的IDEA 版本不同,所以有些细节不太一样

案例1
package com.hspedu.poly_.e1210;
public class Debug01 {
    public static void main(String[] args) {
        //演示逐行执行代码
        int sum = 0;
        for (int i = 0; i < 5; i++) {
            sum += i;
            System.out.println("i=" + i);
            System.out.println("sum=" + i);
        }
        System.out.println("退出 for....");
    }
}
总结:当高光蓝条跳到下一行的时候才会显示上一行的结果

当蓝条跳到
for (int i = 0; i < 5; i++) { 
这一行时,才会显示出变量 sum = 0
执行完毕后的显示

案例2
数组越界
package com.hspedu.poly_.e1210;
public class Debug02 {
    public static void main(String[] args) {
        int[] arr = {1, 10, -1};
        //数组越界异常
        for (int i = 0; i <= args.length; i++) {
            System.out.println(arr[i]);
        }
        System.out.println("退出for");
    }
}
在上述代码中故意将arr.length写成args.length,看一下Debug的流程

提示一个是args,一个是数组arr
输出控制台直接退出程序了

修改之后再次Debug
Debug控制台显示

输出控制台显示


提成程序员思考为什么i可以等于3
案例3
如何追踪源代码
package com.hspedu.poly_.e1210;
import java.util.Arrays;
public class Debug03 {
    public static void main(String[] args) {
        int[] arr = {1, -1, 10, -20, 100};
        //直接使用IDEA提供的方法进行排序
        //需求:想看一下Arrays.sort的底层实现
        Arrays.sort(arr);
        for (int i = 0; i < arr.length; i++) {
            //在Debug之前是按照排序正常输出
            System.out.print(arr[i] + "\t");
        }
    }
}
设置完毕后可按F7(Step Into)进入Arrays.sort方法的底层源码
再次 Step Into

可以一直Step Into,直到找到最底层的源代码
返回(跳出的时候就是Shift + F8,即Step Out)
案例4
演示Resume功能,快捷键F9
package com.hspedu.poly_.e1210;
import java.util.Arrays;
//演示执行到下一个断点,同时支持动态的下断点
public class Debug04 {
    public static void main(String[] args) {
        int[] arr = {1, -1, 10, -20 , 100};
         //直接使用IDEA提供的方法进行排序
        //需求:想看一下Arrays.sort的底层实现
        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");
    }
}
 在第10行和第17行分别下一个断点,在运行Debug之后,按Reseum键,
直接跳到了第二个断点,中间代码的结果也全都输出了


此时Debug还在运行中,但是还可以下断点并运行

练习题
第一题
题目

代码
创建一个Person,有两个private属性,显示定义构造器,重写toString方法,可以输出对象的属性
package com.hspedu.debug_;
public class DebugExercise01 {
    public static void main(String[] args) {
        
        //创建对象的流程
        //(1)加载Person类信息
        //(2)初始化 2.1默认初始化,2.2显式初始化 2.3构造器初始化
        //返回对象地址(知识点:7.9 对象创建的流程分析)
        Person person = new Person("jack", 23);
        System.out.println(person);
    }
}
class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
在Person person = new Person("jack", 23);一行下断点
Force Step Into进入ClassLoader.java(我的没有成功,以下是课程截图),
即第一步:加载Person类信息

第二步:默认初始化(name 为null; age 为0);无法查看
第三步:显式初始化,这里没有给属性赋值
第四步:构造器初始化


 
属性name从null------->jack;age从0------>23
toString方法
Debug输出对象语句,查看是如何调用toString方法

Force Step Into

再次Force Step Into
即(Object obj) 传入一个Person类对象person,此时已经向上转型了
三元运算符号,判断传入的对象是否为null,如果≠null,则调用toString方法,运行类型是Person,运行Person类重写的Object类的toString方法(动态绑定机制)
再次Force Step Into,Person类重写的Object类的toString方法

 连续Step Over
输出
 
 
第二题
题目
使用断点调试,查看动态绑定机制的工作原理
动态绑定机制的代码
package com.hspedu.debug_;
public class DeBugExercise02 {
    public static void main(String[] args) {
        //向上转型,编译类型是A,运行类型是B
        A01 a = new B01();
        //从子类-B类中开始查找
        System.out.println(a.sum());//20+20//30
        System.out.println(a.sum1());//20+10//20
    }
}
class A01 {//父类
    public int i = 10;
    public int sum() {
        return getI() + 10;
    }
    public int sum1() {
        return i + 10;
    }
    public int getI() {
        return i;
    }
}
class B01 extends A01 {//父类
    public int i = 20;
//    public int sum() {
//        return i + 20;
//    }
    public int getI() {
        return i;
    }
//    public int sum1() {
//        return i + 10;
//    }
}
Force Step Into
根据动态绑定机制,调用方法时看运行类型,对象a的的运行类型是B01类,所以先从子类开始查找,由于B01类没有这个方法,就向上父类-A01类中查找

再次Force Step Into
属性是哪里声明就调用哪里的,所以是调用B01的属性20




















