断点调试
- 断点调试的过程中,是运行状态。以对象的运行类型来执行
- 断点调试快捷键:
- F7(跳入) :跳入到方法体内
- F8(跳过):逐行执行代码
- shift+F8(跳出) :跳出方法
- F9(resume,跳到下一个断点执行)
- 退出方法:
想要进入源码的配置
4. 支持在断点调试过程中,动态下断点。可以在自身的代码中下断点,也可以在系统代码中下断点。按下F9如果没有进入下一个断点,则说明业务逻辑并不能执行到那里。
debug对象创建过程
package A;
public class Test {
public static void main(String[] args){
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 +
'}';
}
}
零钱通项目
项目需求
可以完成收益入账,消费,查看明细,退出系统等功能
项目界面
项目改进
设计流程
化繁为简
- 先完成显示菜单,完成交互:给出对应提示信息
- 完成零钱通明细
- 完成收益入账
- 完成消费
- 改进
1、显示菜单与交互(框架)
package com.rxli.smallchange;
import java.util.Scanner;
public class SmallChangeSys {
// 1. 完成显示菜单
public static void main(String[] args) {
//定义相关变量
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.println("请选择(1-4):");
key = scanner.next();
//使用switch分支判断
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("4 退出");
loop = false;
break;
default:
System.out.println("选择有误,请重新选择");
}
}while(loop);
System.out.println("退出了零钱通项目");
}
}
2、零钱通明细功能
思路:(1)可以把收益入账和消费,保存到数组
(2)可以使用对象
(3)用String拼接
3、完成收益入账
//3. 完成收益入账
double money = 0;
double balance = 0;
Date date = null; //date是java.util.Date类型,表示日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); //格式化日期
...
case "2":
System.out.println("2 收益入账");
System.out.println("收益入账金额:");
money = scanner.nextDouble();
//money的值范围应该校验-》一会儿补充
balance += money;
date = new Date(); //获取当前日期
System.out.println();
//拼接收益入账信息到details
details += "\n收益入账\t" + money + "\t" + sdf.format(date) + "\t余额\t" + balance;
break;
4、消费功能
//4. 定义新变量,保存消费的原因
String note = "";
case "3":
System.out.println("消费地点:");
note = scanner.next();
System.out.println("消费金额:");
money = scanner.nextDouble();
//money的值范围应该校验-》一会儿补充
balance -= money;
date = new Date();
details += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t余额\t" + balance;
break;
5、改进
① 用户输入4退出时,给出提示“你确定要退出吗?y/n”,必须输入正确的y/n,否则循环输入指令,直到输入y或者n
注意:一段代码,完成一个小功能,尽量不要混在一起
String choice = "";
case "4":
//while true限制只能输入y或n,否则无限循环
while(true) {
System.out.println("你确定要退出吗?y/n");
choice = scanner.next();
if(choice.equals("y") || choice.equals("n")){
break;
}
}
//再判断输入结果是y还是n,如果是y,则真正地跳出循环
if(choice.equals("y")){
loop = false;
}
break;
② 在收益入账和消费时,判断金额是否合理,并给出相应的提示
思路:找出不正确的条件,然后给出提示,提示完直接break
case "2":
System.out.println("收益入账金额:");
money = scanner.nextDouble();
//校验金额
if(money <= 0){
System.out.println("收益入账金额 需要 大于0");
break;
}
case "3":
//System.out.println("3 消费");
System.out.println("消费地点:");
note = scanner.next();
System.out.println("消费金额:");
money = scanner.nextDouble();
//校验金额
if(money > balance || money < 0){
System.out.println("你的消费金额 应该在 0-" + balance + "元 之间");
break;
}
③ 将面向过程代码修改成面向对象的方法,编写SmallChangeSysOOP.java
类,并使用SmallChangeSysApp.java
完成测试
一个负责调用
一个负责完成功能
SmallChangeSysOOP.java
类
/**
* 该类是完成零钱通各个功能的类
* 使用OOP(面向对象编程)
* 将各个功能对应一个方法
*/
public class SmallChangeSysOOP {
//属性:所有在过程编程中的变量都是属性
boolean loop = true;
Scanner scanner = new Scanner(System.in);
String key = "";
//2. 完成零钱通明细
String details = "------------零钱通明细------------";
//3. 完成收益入账
double money = 0;
double balance = 0;
Date date = null; //date是java.util.Date类型,表示日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
//4. 定义新变量,保存消费的原因
String note = "";
//5. 改进
String choice = "";
//1. 先完成显示菜单,完成交互:给出对应提示信息
public void mainMenu(){
do{
System.out.println("\n============零钱通菜单(OOP)============");
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.println("请选择(1-4):");
key = scanner.next();
//使用switch分支判断
switch(key){
case "1":
this.detail();
break;
case "2":
this.income();
break;
case "3":
this.pay();
break;
case "4":
this.exit();
break;
default:
System.out.println("选择有误,请重新选择(1-4)");
}
}while(loop);
System.out.println("退出了零钱通项目");
}
//2. 完成零钱通明细
public void detail(){
System.out.println(details);
}
//3. 完成收益入账
public void income(){
System.out.println("收益入账金额:");
money = scanner.nextDouble();
//校验金额
if(money <= 0){
System.out.println("收益入账金额 需要 大于0");
return; //退出方法,不再执行后面的代码
}
balance += money;
date = new Date(); //获取当前日期
//拼接收益入账信息到details
details += "\n收益入账\t+" + money + "\t" + sdf.format(date) + "\t余额\t" + balance;
}
//4. 完成消费
public void pay(){
System.out.println("消费地点:");
note = scanner.next();
System.out.println("消费金额:");
money = scanner.nextDouble();
//校验金额
if(money > balance || money < 0){
System.out.println("你的消费金额 应该在 0-" + balance + "元 之间");
return;
}
balance -= money;
date = new Date();
details += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t余额\t" + balance;
}
//5. 改进
public void exit(){
while(true) {
System.out.println("你确定要退出吗?y/n");
choice = scanner.next();
if(choice.equals("y") || choice.equals("n")){
break;
}
}
//再判断输入结果是y还是n,如果是y,则真正地跳出循环
if(choice.equals("y")){
loop = false;
}
}
}
SmallChangeSysApp.java
类
public class SmallChangeSysApp {
public static void main(String[] args) {
new SmallChangeSysOOP().mainMenu();
}
}
优点:便于扩展,逻辑结构清晰
OOP类结构:
本章作业
- 初始化一个Person对象数组(3个人),按照年龄,从大到小排序(用冒泡)
public class Test {
public static void main(String[] args){
Person[] persons = new Person[3];
persons[0] = new Person("aa",20,"w1");
persons[1] = new Person("bb",23,"w2");
persons[2] = new Person("cc",18,"w3");
sort(persons);
for (int i = 0; i < persons.length; i++) {
System.out.println(persons[i]);
}
}
public static void sort(Person[] persons){
Person temp = null;
for (int i = 0; i < persons.length-1; i++) {
for (int j = 0; j < persons.length-i-1; j++) {
if(persons[j].age < persons[j+1].age){
temp = persons[j];
persons[j] = persons[j+1];
persons[j+1] = temp;
}
}
}
}
}
class Person {
String name;
int age;
String job;
public Person(String name, int age, String job) {
this.name = name;
this.age = age;
this.job = job;
}
public Person(){};
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", job='" + job + '\'' +
'}';
}
}
- 如图:
public class Test {
public static void main(String[] args){
Manager aa = new Manager("aa", 200, 30, 1.2);
Worker bb = new Worker("bb", 100, 30, 1.0);
aa.setBonus(1000);
aa.print();
bb.print();
}
}
class Employee {
private String name;
private double dailySalay;
private int day;
private double grade;
public Employee(String name, double dailySalay, int day,double grade) {
this.name = name;
this.dailySalay = dailySalay;
this.day = day;
this.grade = grade;
}
public String getName() {
return name;
}
public double getDailySalay() {
return dailySalay;
}
public int getDay() {
return day;
}
public double getGrade() {
return grade;
}
public void print(){
System.out.println(getName() + "\t工资=" + getDailySalay()*getDay()*getGrade());
}
}
class Worker extends Employee {
public Worker(String name, double dailySalay, int day,double grade){
super(name,dailySalay,day,grade);
}
@Override
public void print() {
System.out.print("普通员工\t");
super.print();
}
}
class Manager extends Employee {
//特有属性
private double bonus;
public Manager(String name, double dailySalay, int day,double grade){
super(name,dailySalay,day,grade);
}
//特有属性不通过构造器,则需要用setter和getter
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
@Override
public void print() {
System.out.println("经理\t" + getName() + "\t工资=" + (bonus+getDailySalay()*getDay()*getGrade()));
}
}
- 如图
public class Test {
public static void main(String[] args){
// CheckingAccount checkingAccount = new CheckingAccount(1000);
// checkingAccount.deposit(10);//1000+10-1 = 1009
// checkingAccount.withdraw(9);//1009-9-1 = 999
// System.out.println(checkingAccount.getBalance());
//测试savingsAccount
SavingsAccount savingsAccount = new SavingsAccount(1000);
savingsAccount.deposit(100);
savingsAccount.deposit(100);
savingsAccount.deposit(100);
System.out.println(savingsAccount.getBalance());//1300
savingsAccount.deposit(100);
System.out.println(savingsAccount.getBalance());//1399
savingsAccount.earnMonthlyInterest();
System.out.println(savingsAccount.getBalance()); //1399 + 13.99 = 1412.99
savingsAccount.withdraw(100);
System.out.println(savingsAccount.getBalance());//1312.99(重置了,免手续)
}
}
class BankAccount {
private double balance;
public BankAccount(double initialBalance){
this.balance = initialBalance;
}
public void deposit(double amount){
balance += amount;
}
public void withdraw(double amount){
balance -= amount;
}
public double getBalance() {
return balance;
}
}
class CheckingAccount extends BankAccount{
public CheckingAccount(double initialBalance) {
super(initialBalance);
}
@Override
public void deposit(double amount){
super.deposit(amount - 1);
}
@Override
public void withdraw(double amount){
super.withdraw(amount + 1);
}
//set和getBalance方法
}
class SavingsAccount extends BankAccount{
private int count = 3;
private double rate = 0.01;
public SavingsAccount(double initialBalance){
super(initialBalance);
}
public void deposit(double amount){
if(count > 0){
super.deposit(amount);
count--;
} else {
super.deposit(amount - 1);
}
}
public void withdraw(double amount){
if(count > 0){
super.withdraw(amount);
count--;
} else {
super.withdraw(amount + 1);
}
}
//每个月初,统计上个月的利息,同时将count=3
public void earnMonthlyInterest(){
count = 3;
super.deposit(getBalance() * rate);
}
}
- 重写equals
@Override
public boolean equals(Object obj){
if(obj == this){
return true;
}
if(! (obj instanceof Doctor)){ //过关斩将,先把异常条件列出来
return false;
}
//obj此时必定是Doctor类型或者其子类型
Doctor tmp = (Doctor)obj;
return this.name.equals(tmp.name) &&
this.age == tmp.age &&
this.gender == tmp.gender &&
this.job.equals(tmp.job) &&
this.sal == tmp.sal;
}
- 向上转型向下转型,动态绑定
public class Test {
public static void main(String[] args){
Person p = new Student();
p.run();//student.run
p.study();//错误,编译过不去
p.eat();//person.eat
Student s = (Student)p;
s.study(); //student.study
s.eat();//person.eat
s.run();//student.run
}
}
class Person {
public void run(){
System.out.println("person.run");
}
public void eat(){
System.out.println("person.eat");
}
}
class Student extends Person{
@Override
public void run(){
System.out.println("student.run");
}
public void study(){
System.out.println("student.study");
}
}
父类不能调用子类的方法
子类可以调用父类的方法
-
==和equals的区别
-
综合作业
要求如下:
打印效果如下:
核心代码段:强调子类对父类的重写,提高复用性
完整代码:
Person.java
public class Person {
private String name;
private char sex;
private int age;
public Person(String name, char sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public char getSex() {
return sex;
}
public int getAge() {
return age;
}
public String play(){
return name + "爱玩";
}
public String basicInfo(){
return "姓名:" + getName() +
"\n年龄:" + getAge() +
"\n性别:" + getSex();
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
'}';
}
}
Student.java
package com.rxli.homework13;
public class Student extends Person{
private String stu_id;
public Student(String name, char sex, int age, String stu_id) {
super(name,sex,age);
this.stu_id = stu_id;
}
public void study(){
System.out.println("我承诺,我会好好学习.");
}
@Override
public String play(){
return super.play() + "足球";
}
public void print() {
System.out.println("学生的信息:");
System.out.println(basicInfo());
System.out.println("学号:" + stu_id);
study();
System.out.println(play());
}
@Override
public String toString() {
return "Student{" +
"stu_id='" + stu_id + '\'' +
'}' + super.toString();
}
}
Teacher.java
package com.rxli.homework13;
public class Teacher extends Person{
private int work_age;
public Teacher(String name, char sex, int age, int work_age) {
super(name,sex,age);
this.work_age = work_age;
}
public void teach(){
System.out.println("我承诺,我会认真教学。");
}
@Override
public String play(){
return super.play() + "象棋";
}
public void print() {
System.out.println("老师的信息:");
System.out.println(basicInfo());
System.out.println("工龄:" + work_age);
teach();
System.out.println(play());
}
@Override
public String toString() {
return "Teacher{" +
"work_age=" + work_age +
'}' + super.toString();
}
}
Test.java
package com.rxli.homework13;
public class Test {
public static void main(String[] args){
Person[] persons = new Person[4];
persons[0] = new Student("aa", '女', 20, "1000");
persons[1] = new Student("bb", '男', 22, "2000");
persons[2] = new Teacher("cc", '女', 39, 15);
persons[3] = new Teacher("dd", '男', 40, 16);
//排序
sort(persons);
//打印数组
for(int i = 0 ; i < persons.length ; i++){
test(persons[i]);
}
}
public static void sort(Person[] persons){
Person tmp = null;
for(int i = 0 ; i < persons.length - 1 ; i++){
for(int j = 0 ; j < persons.length - i - 1 ; j++){
if(persons[j].getAge() < persons[j+1].getAge()){
tmp = persons[j];
persons[j] = persons[j+1];
persons[j+1] = tmp;
}
}
}
}
public static void test(Person p) {
if(p instanceof Student){
((Student)p).print();
}
if(p instanceof Teacher){
((Teacher)p).print();
}
System.out.println("--------------------------");
}
}
- 程序阅读题,给出输出结果
答案:
我是A类
hahah我是B类的有参构造
我是C类的有参构造
我是C类的无参构造
子类构造器中如果没有this和super时,才会在首行调用父类的无参构造器
- 什么是多态,多态具体体现有哪些
-
多态:方法或对象具有多种形态,是OOP的第三大特征,是建立在封装和继承基础之上
-
多态的具体体现:
- 方法多态:
①重载体现多态
②重写体现多态 - 对象多态:
①对象的编译类型和运行类型可以不一致,编译类型在定义时就确定,不能变化
②对象的运行类型可以变化,运行类型可以用getClass获得
- 方法多态:
public class Test {
public static void main(String[] args){
AAA obj = new BBB(); //向上转型
System.out.println(obj.getClass());
AAA b1 = obj;
obj = new CCC(); //向上转型(只要是obj编译类型下的子类,都可以向上转型把地址赋给obj
System.out.println(obj.getClass());
obj = b1;
System.out.println(obj.getClass());
}
}
class AAA {
}
class BBB extends AAA {
}
class CCC extends BBB{
}