0、Debug的步骤
Debug(调试)程序步骤如下:
1、添加断点
2、启动调试
3、单步执行
4、观察变量和执行流程,找到并解决问题
1、添加断点
在源代码文件中,在想要设置断点的代码行的前面的标记行处,单击鼠标左键就可以设置断点,在相同位置再次单击即可取消断点。
2、启动调试
示例代码:
public class Debug01 {
public static void main(String[] args) {
//1.
int m = 10;
int n = 20;
System.out.println("m = " + m + ",n = " + n);
swap(m, n);
System.out.println("m = " + m + ",n = " + n);
//2.
int[] arr = new int[] {1,2,3,4,5};
System.out.println(arr);//地址值
char[] arr1 = new char[] {'a','b','c'};
System.out.println(arr1);//abc
}
public static void swap(int m, int n) {
int temp = m;
m = n;
n = temp;
}
}
启动调试:IDEA提供多种方式来启动程序(Launch)的调试,
分别是通过菜单(Run –> Debug)、图标(“绿色臭虫”)等等
如果你还是用Run启动,那就不会出现debug效果,断点跟没有打一样:
启动调试:方法一
方法二
方法三:
代码会停留在我们第一个打断点的位置:只是走到这个断点的位置,此行代码还没有被执行:
1、 Step Over(F8):
单步执行,进入下一步,如果当前行断点是调用一个方法,则不进入当前方法体内:
蓝色高亮的那一行是我们即将要执行的语句,不是已经执行完毕的语句
单步执行,如果当前行断点是调用一个方法,则不进入当前方法体内,也就是说你看不到方法内部的执行情况,这里你看不到swap(m,n)的执行情况,此时你要用到:
当我们点击Step into时:
再Step into一下:
跳出此方法:
如果你现在在main方法中,你点击step out的话,main方法就执行结束了,结束的是当前方法!
Resume Program(F9):恢复程序运行,但如果该断点下面还有断点则停在下一个断点上:
Run to Cursor(Alt + F9):直接跳到光标处继续调试
多种Debug情况介绍
行断点
断点打在代码所在的行上。执行到此行时,会停下来。我们上面的例子都是行断点
方法断点
断点设置在方法的签名上,当执行此方法时,断点可以被唤醒,也可以设置在当执行完方法退出时,断点也被唤醒:
进入方法的时候会做一个停留,你也可以设置当执行完方法的时候也做一个停留
如果我对父类中的方法、接口中的抽象方法进行方法断点呢?
当调用了子类的test方法时:(我们明明没在子类的test方法上打断点,但是也停留了)
同理,直接唤醒到我们接口的实现类方法的位置:
你也可以对源码进行方法断点!
字段断点
在进行修改的时候就会起作用
public class Debug03 {
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, 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 +
'}';
}
}
id变量默认值为0,所以赋值为1也算作修改:private int id = 1;
当调用对属性值进行修改的地方就会起作用,读取属性值不起作用:
这样的话除了前面的三次停留,还会有第四次停留:
如果你的程序中发现你的某个字段值并不是你想要的结果,那么你就可以加上字段断点,看看有哪些地方对它进行了修改。
条件断点
在满足某个条件的情况下,断点就会起作用!
public class Debug04 {
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的条件下,执行断点:
异常断点
对异常进行跟踪。如果程序出现指定异常,程序就会执行断点,自动停住
程序出异常了,在终止之前,这个debug就会起作用
public class Debug05 {
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());
}
}
你现在可以点击➕,来添加一个异常断点:
以Debug的方式启动程序,此时代码就停留在这里了,因为出现了一个算数异常
你也可以加上其他异常断点,例如空指针异常:
线程调试:
public class Debug06 {
public static void main(String[] args) {
test("Thread1");
test("Thread2");
}
public static void test(String threadName) {
new Thread(
() -> System.out.println(Thread.currentThread().getName()),
threadName
).start();
}
}