327. 断点调试(Debug)
一个实际需求
- 在开发中,程序员在查找错误时,可用断点模式
- 在断点调试过程中,是运行状态,是以对象的运行类型来执行的。
A extends B; B b = new A(); b.xx();//按照运行类型来执行的
断点调试介绍
- 断点调试是指在程序的某一步设置一个断点,调试时,程序运行到这一行就会挺住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错代码行即显示错误,停下,进行分析而找到这个Bug。
- 断点调试是程序员必须掌握的技能
- 断点调试也能帮助我们查看java底层源码的执行过程,提高程序员的Java水平。
断点调试的快捷键
- F7(跳入):跳入方法体内执行
- F8(跳过):逐行执行代码
- shift+F8(跳出):跳出方法
- F9(resume):执行到下一个断点
328. 断点调试案例1
329. 断点调试案例2
数组越界案例
330. 断点调试案例3
如何追源代码,看看java设计者是怎么实现的。
按F7进入方法体(没进去)
方法1:强制进入方法体
方法2:配置一下就好了
默认情况下不让你进入类的源码中
这次按F7就进入了
真正完成排序的是一个双重快速排序
回到主方法中“Arrays.sort(arr)"的下一行,一层一层跳回去。用shift+F8
331 断点调试案例4
演示如何直接执行到下一个断点F9 resume
断点可以在debug过程中,动态的下断点
动态加断点,然后执行到下一个断点
332. 断点调试案例5
DebugExercise.java
- 使用断点调试的方法,追踪下一个对象创建的过程。Person[name ,age, 构造器…]
//演示对象创建过程,加深对调试的理解
public class DebugExecrise {
public static void main(String[] args) {
//创建对象的流程
//(1)加载Person类信息
//(2)初始化(2.1)默认初始化;(2.2)显示初始化;(2.3)构造器初始化
//(3)返回对象的地址
Person jack = new Person("jack", 20);
System.out.println(jack);
}
}
class Person{
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
强制步入
查看toString
333. 断点调试案例6
我们使用断点调试,查看动态绑定机制如何工作。
A.java
package com.masterspark;
public class A {
public int i = 10;
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public int sum(){
return getI() + 10;
}
}
B.java
package com.masterspark;
public class B extends A{
public int i = 20;
}
Main.java
import com.masterspark.A;
import com.masterspark.B;
import java.util.Arrays;
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {
public static void main(String[] args) {
//debug动态绑定机制
A a = new B();
System.out.println(a.sum());
}
}
设置断点
进入到父类的sum方法
a本身运行类型是B,它应该找B类的sum方法,但是B类没有sum方法,于是去找父类A类的sum方法,调用getI方法,但是子类没有,又用负类的getI,
属性没有动态绑定机制,所以属性用的是编译类型A的成员,即i为10
所以最后输出的结果是20
334. 零钱通项目介绍
- 使用 Java 开发 零钱通项目 , 可以完成收益入账,消费,查看明细,退出系统等功能.
界面:
先做过程编程,再写面向对象版本
化繁为简.
- 先完成显示菜单,并可以选择
- 完成零钱通明细.
- 完成收益入账
- 消费
- 退出
335. 零钱通菜单
完成零钱通菜单
SmallChangeSys.java
package com.masterspark.smallchange;
import java.util.Scanner;
public class SmallChangeSys {
public static void main(String[] args) {
//1. 先完成显示菜单,并可以选择菜单,给出对应的提示
//定义变量
boolean loop = true;//是否需要循环显示
Scanner scanner = new Scanner(System.in);
String key = "";//输入的选择
do{
System.out.println("=========零钱通菜单=========");
System.out.println("\t\t\t1 零钱通明细");
System.out.println("\t\t\t2 收益入账");
System.out.println("\t\t\t3 消费情况");
System.out.println("\t\t\t4 退出系统");
System.out.print("请选择(1-4)");
key = scanner.next();
//使用siwtch分支结构
switch(key){
case "1":
System.out.println("1 零钱通明细");
break;
case "2":
System.out.println("2 收益入账");
break;
case "3":
System.out.println("3 消费情况");
break;
case "4":
System.out.println("------退出了零钱通-------");
loop=false;//退出循环
break;
default:
System.out.println("菜单选择有误,请重新选择");
}
}while(loop);
}
}
运行结果:
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)1
1 零钱通明细
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)2
2 收益入账
1 零钱通明细
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)3
3 消费情况
1 零钱通明细
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)d
菜单选择有误,请重新选择
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)4
------退出了零钱通-------
进程已结束,退出代码为 0
336. 零钱通明细
完成零钱通明细。
package com.masterspark.smallchange;
import java.util.Scanner;
public class SmallChangeSys {
public static void main(String[] args) {
//1. 先完成显示菜单,并可以选择菜单,给出对应的提示
//定义变量
boolean loop = true;//是否需要循环显示
Scanner scanner = new Scanner(System.in);
String key = "";//输入的选择
//完成零钱通明细
//思路:(1)收益入账和消费保存到数组
//(2)使用对象完成
//(3)简单的话使用String拼接
//使用第三个
String details = "-------零钱通明细-------";
do{
System.out.println("=========零钱通菜单=========");
System.out.println("\t\t\t1 零钱通明细");
System.out.println("\t\t\t2 收益入账");
System.out.println("\t\t\t3 消费情况");
System.out.println("\t\t\t4 退出系统");
System.out.print("请选择(1-4)");
key = scanner.next();
//使用siwtch分支结构
switch(key){
case "1":
System.out.println(details);
break;
case "2":
System.out.println("2 收益入账");
break;
case "3":
System.out.println("3 消费情况");
break;
case "4":
System.out.println("------退出了零钱通-------");
loop=false;//退出循环
break;
default:
System.out.println("菜单选择有误,请重新选择");
}
}while(loop);
}
}
运行结果:
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)1
-------零钱通明细-------
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)4
------退出了零钱通-------
进程已结束,退出代码为 0
337 零钱通收益
完成收益入账
package com.masterspark.smallchange;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
public class SmallChangeSys {
public static void main(String[] args) {
//1. 先完成显示菜单,并可以选择菜单,给出对应的提示
//定义变量
boolean loop = true;//是否需要循环显示
Scanner scanner = new Scanner(System.in);
String key = "";//输入的选择
//完成零钱通明细
//思路:(1)收益入账和消费保存到数组
//(2)使用对象完成
//(3)简单的话使用String拼接
//使用第三个
String details = "-------零钱通明细-------";
//3. 完成收益入账
//思路:定义新的变量,完成功能驱动程序员增加新的变化和代码
double money = 0.0;
double balance = 0.0;//🈷
Date date = null;//data是java.util.date类型
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");//可以用于日期格式化的对象
do{
System.out.println("=========零钱通菜单=========");
System.out.println("\t\t\t1 零钱通明细");
System.out.println("\t\t\t2 收益入账");
System.out.println("\t\t\t3 消费情况");
System.out.println("\t\t\t4 退出系统");
System.out.print("请选择(1-4)");
key = scanner.next();
//使用siwtch分支结构
switch(key){
case "1":
System.out.println(details);
break;
case "2":
System.out.print("收1益入账金额:");
money = scanner.nextDouble();
//money的值的范围应该校验一下
//一会再完善
balance += money;
//拼接收益入账信息到details
date = new Date();//获取当前的日期
details += "\n收益入账\t+" + money + "\t" + sdf.format(date) + "\t" +balance;
System.out.println(details);
break;
case "3":
System.out.println("3 消费情况");
break;
case "4":
System.out.println("------退出了零钱通-------");
loop=false;//退出循环
break;
default:
System.out.println("菜单选择有误,请重新选择");
}
}while(loop);
}
}
运行结果:
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)2
收益入账金额:114514
-------零钱通明细-------
收益入账 +114514.0 2025-01-13 11:23 114514.0
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)2
收益入账金额:1919
-------零钱通明细-------
收益入账 +114514.0 2025-01-13 11:23 114514.0
收益入账 +1919.0 2025-01-13 11:23 116433.0
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)2
收益入账金额:10
-------零钱通明细-------
收益入账 +114514.0 2025-01-13 11:23 114514.0
收益入账 +1919.0 2025-01-13 11:23 116433.0
收益入账 +10.0 2025-01-13 11:24 116443.0
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)1
-------零钱通明细-------
收益入账 +114514.0 2025-01-13 11:23 114514.0
收益入账 +1919.0 2025-01-13 11:23 116433.0
收益入账 +10.0 2025-01-13 11:24 116443.0
=========零钱通菜单=========
1 零钱通明细
2 收益入账
3 消费情况
4 退出系统
请选择(1-4)