4.断点调试

1.IDEA断点调试(Debug)

1.1.为什么需要Debug

编好的程序在执行过程中如果出现错误,该如何查找或定位错误呢?简单的代码直接就可以看出来,但
如果代码比较复杂,就需要借助程序调试来查找错误了。

 

运行编写好的程序时,可能出现的几种情况:
> 情况1:没有任何bug,程序执行正确!
====================如果出现如下的三种情况,都又必要使用debug=============================
> 情况2:运行以后,出现了错误或异常信息。但是通过日志文件或控制台,显示了异常信息的位置。
> 情况3:运行以后,得到了结果,但是结果不是我们想要的。
> 情况4:运行以后,得到了结果,结果大概率是我们想要的。但是多次运行的话,可能会出现不是我们想要的情况。
比如:多线程情况下,处理线程安全问题。

1.2.Debug的步骤

Debug(调试)程序步骤如下:
1、添加断点
2、启动调试
3、单步执行
4、观察变量和执行流程,找到并解决问题

添加断点

在源代码文件中,在想要设置断点的代码行的前面的标记行处,单击鼠标左键就可以设置断点,在相同
位置再次单击即可取消断点。

 启动调试

 单步调试工具介绍

 

 1.3.方法断点

  • 断点设置在方法的签名上,默认当进入时,断点可以被唤醒。
  • 也可以设置在方法退出时,断点也被唤醒
import java.util.HashMap;

public class Debug02 {
    public static void main(String[] args) {
//        //1.
//        Son instance=new Son();
//        instance.test();
        //2.类的多态性
        Father instance1 = new Son();
        instance1.test();
        //3.接口的多态性
        Consumer con=new ConsumerImpl();
        con.accept("你好啊");
        //4.
        HashMap map = new HashMap();
        map.put("tom",12);
        map.put("jerry",11);
        map.put("tony",14);
    }
}
class Father{
    public void test(){
        System.out.println("Father:test1");
        System.out.println("Father:test2");
    }
}
class Son extends Father{
    @Override
    public void test(){
        System.out.println("Father:test1");
        System.out.println("Father:test2");
    }
}
interface Consumer{
    void accept(String str);
}
class ConsumerImpl implements Consumer{
    @Override
    public void accept(String str){
        System.out.println("ConsumerImple:"+str);
    }
}

  • 在多态的场景下,在父类或接口的方法上打断点,会自动调入到子类或实现类的方法

1.4.字段断点

  • 在类的属性声明上打断点,默认对属性的修改操作进行监控

public class Debug02 {
    public static void main(String[] args) {
        Person p1 = new Person(3);
        System.out.println(p1);
    }
}
class Person {
    private int id = 1;
    private String name;
    private int age;

    public Person() {
    }

    {
        id = 2;
    }

    public Person(int id) {
        this.id = id;
    }
}
public Person(int id) {
        this.id = id;
    }

    public Person(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    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{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

1.5.条件断点

public class Debug03 {
    public static void main(String[] args) {
        int[]arr=new int[]{1,2,3,4,5,6,7,8,9,10,11,12};
        for (int i = 0; i < arr.length; i++) {
            int target=arr[i];
            System.out.println(target);
        }
    }
}

针对上述代码,在满足arr[i]%3==0的条件下,执行断点。

 1.6.异常断点

  • 对异常进行跟踪。如果程序出现指定异常,程序就会执行断点,自动停住。
public class Debug04 {
    public static void main(String[] args) {
        int m=10;
        int n=0;
        int result=m/n;
        System.out.println(result);

        //空指针异常
        Person p1 = new Person(1001);
        System.out.println(p1.getName().toUpperCase());
    }
}

 

 1.7.线程调

public class Dubug5 {
    public static void main(String[] args) {
        test("Thread1");
        test("Thread2");
    }
    public static void test(String threadName){
        new Thread(
                ()-> {
                    for(int i=0;i<100;i++){
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                },
                threadName
        ).start();
    }
}

 1.8.强制结束

public class Debug6 {
    public static void main(String[] args) {
        System.out.println("获取请求的数据");
        System.out.println("调用写入数据库的方法");
        insert();
        System.out.println("程序结束");
    }

    private static void insert() {
        System.out.println("进入insert()方法");
        System.out.println("获取数据库连接");
        System.out.println("将数据写入数据表中");
        System.out.println("写出操作完成");
        System.out.println("断开连接");
    }
}

 1.9.自定义调试数据试图

public class Debug7 {
    public static void main(String[] args) {
        HashMap<Integer,String> map = new HashMap<>();
        map.put(1,"高铁");
        map.put(2,"网购");
        map.put(3,"支付宝");
        map.put(4,"共享单车");
        System.out.println(map);
    }
}

设置如下;

 1.10.常见问题

问题:使用Step Into时,会出现无法进入源码的情况。如何解决?
方案1:使用 force step into 即可
方案2:点击Setting -> Build,Execution,Deployment -> Debugger -> Stepping
把Do not step into the classess中的 java.* 、 javax.* 取消勾选即可。

 

posted on 2023-09-27 14:35  情生意动  阅读(20)  评论(0)    收藏  举报