JAVA学习笔记——第七章 面向对象中级(二)

一、零钱通项目练习

深刻理解面向对象编程的好处,包括复用性等等。

1.1 面向过程编程

package lingqian;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class smallchance {
    //步骤
    //1.先完成显示菜单,并可以选择菜单,给出对应的提示
    //2.完成零钱通明细
    //3.完成收益入账
    //4.完成消费
    //5.退出
    //6.退出时给出提示确定要退出吗输入y/n
    //7.收益入账和消费的时候金额是否合理(找出不正确金额的条件给出提示)

    //菜单必须显示一次所以用dowhille
    public static void main(String[] args) {
        //1.先完成显示菜单,并可以选择菜单,给出对应的提示
        //定义相关的变量
        boolean loop = true;
        Scanner scanner = new Scanner(System.in);
        String key ="";
        //2.完成零钱通明细
        String details =  "\n=================零钱通明细===============";//打算用字符串拼接来做
        //3.完成收益入账
        //定义新变量
        double money = 0;
        double balance = 0;
        Date date = null;//date 是java.util.lang的类型表示日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");//用于日期格式化的袷对象
        //4.消费
        //定义新变量接受\
        String order;
        do{
            System.out.println("\n=================零钱通菜单===============");
            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(details);
                    break;
                case "2":
                    System.out.println("2 收益入账金额");
                    money = scanner.nextDouble();
                    //找出不正确金额的条件给出提示
                    if(money <= 0){
                        System.out.println("收益入账金额需要大于0");
                        break;
                    }
                    date = new Date();
                    balance += money;
                    details += "\n收益入账\t" + money + "\t" + sdf.format(date) + "\t" + balance;
                   // System.out.println(sdf.format(date));日期初始化
                    break;
                case "3":
                    System.out.println("3 消费金额");
                    money = scanner.nextDouble();
                    if(money <= 0 || money > balance){
                        System.out.println("请输入正确的消费金额");
                        break;
                    }
                    System.out.println("请输入消费项目");
                    order = scanner.next();
                    date = new Date();
                    balance -= money;
                    details += "\n" + order + "\t-" + money + '\t' + sdf.format(date) + "\t" + balance;
                    break;
                case "4":
                    //这里很巧妙,高内聚低耦合
                    String choice;
                    while(true){
                        System.out.println("请确认是否要退出,输入y/n");
                        choice = scanner.next();
                        if(choice.equals("y") || choice.equals("n")){
                            break;
                        }
                    }
                    if(choice.equals("y")){
                        loop = false;}
                    break;
                default:
                    System.out.println("菜单选择有误,请重新选择");
            }
        }while(loop);//不停显示菜单的过程
        System.out.println("退出了零钱通项目");
    }
}

1.2 面向对象编程

可以直接按照1.1的改写把每一个功能都写进方法里面

package lingqian;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;


public class oop {//完成各个功能的
    //属性
    boolean loop = true;
    Scanner scanner = new Scanner(System.in);
    String key ="";
    //2.完成零钱通明细
    String details =  "\n=================零钱通明细===============";//打算用字符串拼接来做
    //3.完成收益入账
    //定义新变量
    double money = 0;
    double balance = 0;
    Date date = null;//date 是java.util.lang的类型表示日期
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");//用于日期格式化的袷对象
    //4.消费
    //定义新变量接受\
    String order;

    //菜单
    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.out();
                    break;
                default:
                    System.out.println("菜单选择有误,请重新选择");
            }
        }while(loop);//不停显示菜单的过程
    }
    //明细
    public void detail(){
        System.out.println(details);
    }
    //入账
    public void income(){
        System.out.println("2 收益入账金额");
        money = scanner.nextDouble();
        //找出不正确金额的条件给出提示
        if(money <= 0){
            System.out.println("收益入账金额需要大于0");
            return;//退出方法不再执行后的代码
        }
        date = new Date();
        balance += money;
        details += "\n收益入账\t" + money + "\t" + sdf.format(date) + "\t" + balance;
        // System.out.println(sdf.format(date));日期初始化
    }
    //消费
    public void pay(){
        System.out.println("3 消费金额");
        money = scanner.nextDouble();
        if(money <= 0 || money > balance){
            System.out.println("请输入正确的消费金额");
            return;
        }
        System.out.println("请输入消费项目");
        order = scanner.next();
        date = new Date();
        balance -= money;
        details += "\n" + order + "\t-" + money + '\t' + sdf.format(date) + "\t" + balance;
    }
    public void out(){
        String choice;
        while(true){
            System.out.println("请确认是否要退出,输入y/n");
            choice = scanner.next();
            if(choice.equals("y") || choice.equals("n")){
                break;
            }
        }
        if(choice.equals("y")){
            loop = false;}
    }
}
//调用一下
package lingqian;

public class smallchancesystemapp{
     public static void main(String[] args) {
       new oop().mainmenu();
   }
}

二、 练习题

2.1 练习1

  注意熟练冒泡排序(两层for加一个临时变量tmp)和这个初始化person对象数组。

package lianxi;

public class demo1 {
    public static void main(String[] args) {
//        Person person1 = new Person("Tom",15,"student");
//        Person person2 = new Person("pig",17,"student");
//        Person person3 = new Person("dog",18,"student");
        //初始化Person对象数组,有3个person对象
        Person[] persons = new Person[3];
        persons[0] = new Person("jack",10,"javaee工程师");
        persons[1] = new Person("tom",60,"大数据工程师");
        persons[2] = new Person("tommy",50,"人工只能工程师");
        //输出当前的对象数组
        for (int i = 0; i < persons.length; i++) {
            System.out.println(persons[i]);//默认执行对象的tostring
        }
        //使用冒泡排序按照age从大到小排序
       Person tmp = null;
        for (int i = 0; i < persons.length - 1; i++) {
            for (int j = 0; j < persons.length - 1 - i; j++) {
                if(persons[j].getAge() < persons[j + 1].getAge()){
                    tmp = persons[j];
                    persons[j] = persons[j + 1];
                    persons[j + 1] = tmp;

                }
            }
        }
        for (int i = 0; i < persons.length; i++) {
            System.out.println(persons[i]);
        }

    }
}

class  Person{
    private String name;
    private int age;
    private String job;

    public Person(String name, int age, String job) {
        this.name = name;
        this.age = age;
        this.job = job;
    }

    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;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", job='" + job + '\'' +
                '}';
    }
}

 2.2 练习2

本类同包子类不同包
public
protected
默认
private

 2.3 练习3

没啥特殊的,非常简单,复习一下继承 

package lianxi;

import java.util.function.Predicate;

public class demo3 {
    public static void main(String[] args) {
        Professor professor = new Professor("baoyu", 30, "高级职称", 30000, 1.1);
        professor.introduce();
    }
}


class Teacher{
    private String name;
    private int age;
    private String post;//职称
    private double salary;
   //增加一个工资级别
    private double grade;

    public Teacher(String name, int age, String post, double salary, double grade) {
        this.name = name;
        this.age = age;
        this.post = post;
        this.salary = salary;
        this.grade = grade;
    }

    public double getGrade() {
        return grade;
    }

    public void setGrade(double grade) {
        this.grade = grade;
    }

    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;
    }

    public String getPost() {
        return post;
    }

    public void setPost(String post) {
        this.post = post;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public void introduce(){
        System.out.println("name" + name + " age" + age + " post" + post + " salary" + salary + " grade" + grade);
    }
}



class  Professor extends Teacher{
    public Professor(String name, int age, String post, double salary, double grade) {
        super(name, age, post, salary, grade);
    }

    @Override
    public void introduce(){
        System.out.println("这是教授的信息");
        super.introduce();
    }
}

 2.4 练习4 

题目很简单,考察的点就一个,OOP的复用思想,在打印工资的时候。 

package lianxi;

public class demo4 {
    public static void main(String[] args) {
        manager tom = new manager("tom", 20, 100, 1.2);
        tom.setBonus(3000);
        tom.printsal();
        commonworker pig = new commonworker("pig", 20, 80, 1.1);
        pig.printsal();
    }
    }
class worker{
    private String name;
    private  int workday;
    private double daysal;
    private double grade;

    public worker(String name, int workday, double daysal, double grade) {
        this.name = name;
        this.workday = workday;
        this.daysal = daysal;
        this.grade = grade;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getWorkday() {
        return workday;
    }
    public void setWorkday(int workday) {
        this.workday = workday;
    }
    public double getDaysal() {
        return daysal;
    }
    public void setDaysal(double daysal) {
        this.daysal = daysal;
    }
    public double getGrade() {
        return grade;
    }
    public void setGrade(double grade) {
        this.grade = grade;
    }
    public double printsal(){
        return(daysal * workday * grade);
    }
}

class manager extends worker{
    private double bonus = 1000;
    //创建manager时候,不确定奖金在构造器中
    public manager(String name,  int workday, double daysal, double grade) {
        super(name,  workday, daysal, grade);
    }



    public void setBonus(double bonus) {
        this.bonus = bonus;
    }

    @Override
    public double printsal(){
        System.out.println("经理" + getName() + "工资是 :" +(bonus + super.printsal()));
        return 0;
    }
}
class commonworker extends worker{
    public commonworker(String name, int workday, double daysal, double grade) {
        super(name,  workday, daysal, grade);
    }
    @Override
    public double printsal(){
        System.out.println("员工" + getName() + "工资是" + super.printsal());
        return 0;
    }

}

2.5 练习5

super是看父类的如果没有的再看超类的,this是先看本类的没有再往上找

father:super能访问的是super.name,super.g1().

            this能访问的是this.id,this.score,this.f1(),this.name,this.g1()

Son :super能调用的是super.id,super.f1(),super.name,super.g1()

          this能访问的this.name,this.g1(),this.show(),this.id,this.f1().this.g1()

 2.6 练习6

 ​​​​​

 两个匿名对象,注意创建构造器的时候的操作

答案:Test,Demo,Rose,Jack,John(把父类的name修改成john),Jack

2.7 练习7

 体会重写的好处,第二个重写的时候,设置count =3次,做判断

package lianxi;

import jdk.nashorn.internal.ir.SplitReturn;

public class demo7 {
    public static void main(String[] args) {
        //1)
        CheckingAccount checkingAccount = new CheckingAccount(1000);
        checkingAccount.deposit(10);//1009
        System.out.println(checkingAccount.getBalcance());
        checkingAccount.withdraw(10);//998
        System.out.println(checkingAccount.getBalcance());

        //2)
        SavingsAccount savingsAccount = new SavingsAccount(1000);
        savingsAccount.deposit(10);
        savingsAccount.withdraw(10);
        savingsAccount.deposit(10);
        savingsAccount.deposit(10);
        System.out.println(savingsAccount.getBalcance());
        //月初,定时器自动调用一下earnmoneyInterest
        savingsAccount.earnMoneyInterest();
        savingsAccount.deposit(10);
        System.out.println(savingsAccount.getBalcance());
    }
}

class BankAccount{
    private double balance;//余额
    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }
    //存款
    public void deposit(double amount) {
        this.balance += amount;
    }
    //取款
    public void withdraw(double amount){
        this.balance -= amount;
    }

    public double getBalcance() {
        return balance;
    }

    public void setBalcance(double balcance) {
        this.balance = balcance;
    }
}
//1)
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);
    }
}
//2)
class SavingsAccount extends BankAccount{
    private int count = 3;//三次机会
    private double rate = 0.01;//利率

    //每个月初,进行次数的重置 ,同时计算存款的利息
    public void earnMoneyInterest(){
        count = 3;
        super.deposit(super.getBalcance() * rate);
    }
    public SavingsAccount(double initialBalance) {
        super(initialBalance);
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public double getRate() {
        return rate;
    }

    public void setRate(double rate) {
        this.rate = rate;
    }

    @Override
    public void deposit(double amount) {
        //判断是否还有免手续费的机会
        if(count <= 0){
            super.deposit(amount - 1);
        }
       else{
           count --;
           super.deposit(amount);
        }
    }

    @Override
    public void withdraw(double amount) {
        if(count <= 0) {
            super.withdraw(amount + 1);
        }
        else{
            super.withdraw(amount);
        }
    }
}

2.8 练习8

class Point{
    private double x;
    private double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

class LabeledPointed extends Point{
    private String label;

    public LabeledPointed(String label,double x, double y) {
        super(x, y);
        this.label = label;
    }
}

这个题目的关键点是向下转型,因为你要用到属性需要的是Doctor的属性,属性要看编译类型

class Doctor{
    private String name;
    private int age;
    private String job;
    private String gender;
    private double salary;

    public Doctor(String name, int age, String job, String gender, double salary) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.gender = gender;
        this.salary = salary;
    }

    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;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public boolean equals(Object obj) {
        if(this == obj){
            return true;
        }
        if(!(obj instanceof Doctor)){
            return false;
        }
        //这里要有一个向下转型,因为obj是OBJECt类,没有对应属性 ,向下转型可以调用子类的特有方法
        Doctor doctor = (Doctor)obj;
        return this.name.equals(doctor.name) && this.age == doctor.age && this.job.equals(doctor.job) && this.salary == doctor.salary && this.gender.equals(doctor.gender);
    }
}

 *2.9 练习9

这个题目非常重要的一个点,因为就是在写代码的时候,编译器只认编译类型,运行的时候,才去认运行类型,所以在向上转型以后,study方法是用不了的!!!,只能用run和eat但是在运行的时候,看运行类型,run调用的是子类的,eat子类里没有所以去父类里面找。

package lianxi;

public class demo11 {
    public static void main(String[] args) {
        //向上转型
        Person1 p = new Student();
        p.run();//走的student
        p.eat();//student没有,调父类的
        //向下转型:把指向子类对象的父类引用,转成指向子类对象的子类引用
        Student s = (Student)p;
        s.run();//student
        s.study();//student
        s.eat();//Person1
    }
}
class Person1{
    public void run(){System.out.println("person run");}
    public void eat(){System.out.println("person eat");}
}

class Student extends Person1{
    public void run(){System.out.println("student run");}
    public void study(){System.out.println("student study");}
}

 2.10 练习10 

 答案:

 *2.11 练习11 

此题目综合性较强需要注意的是以下几点

  1. 在(7)做多态数组的是时候,排序使用经典的冒泡排序
  2. 在(8)中做特殊功能的时候,使用多态的向下转型 ,其他的都不难
  3. 输出的时候重写tostring
package lianxi;

public class demo12 {
    public static void main(String[] args) {
        //多态数组排序
        Person2 persons[] = new Person2[4];
        persons[0] = new Student1("Jack","男",11,0001);
        persons[1] = new Student1("mary","女",20,0002);
        persons[2] = new Teacher1("smith","女",36,5);
        persons[3] = new Teacher1("scot","男",26,1);

        paixu paixu = new paixu();
        paixu.bubblesort(persons);
        //输出排序后的信息,提前重写一下tostring方法
        System.out.println("-----------排序后的数组情况--------------");
        for (int i = 0; i < persons.length; i++) {
            System.out.println(persons[i]);//默认运行tostring
        }
        //遍历数组的时候调用test方法
        for (int i = 0; i < persons.length; i++) {
            paixu.test(persons[i]);
        }

    }
}
class Student1 extends Person2{
    private int stu_id;

    public Student1(String name, String sex, int age, int stu_id) {
        super(name, sex, age);
        this.stu_id = stu_id;
    }

    public int getStu_id() {
        return stu_id;
    }

    public void setStu_id(int stu_id) {
        this.stu_id = stu_id;
    }

    //学习方法
    public void study(){
        System.out.println( getName() +"承诺我会好好学习");
    }

    @Override
    public String play() {
       return super.play() + "篮球";
    }
    //重写tostring

    @Override
    public String toString() {
        return "Student1{" +
                "stu_id=" + stu_id +
                '}' + super.toString();
    }
}

class Teacher1 extends Person2{
    private int work_age;

    public Teacher1(String name, String sex, int age, int work_age) {
        super(name, sex, age);
        this.work_age = work_age;
    }

    public int getWork_age() {
        return work_age;
    }

    public void setWork_age(int work_age) {
        this.work_age = work_age;
    }

    //教学方法
    public void  teach(){
        System.out.println(getName() +"承诺我回认真教学");
    }

    @Override
    public String play() {
       return  super.play()+ "象棋";
    }

    //重写tostring

    @Override
    public String toString() {
        return "Teacher1{" +
                "work_age=" + work_age +
                '}' + super.toString();
    }
}

class Person2{
    private String name;
    private String sex;
    private int age;

    public Person2(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String play(){
        return (name + "爱玩");
    }

    //


    @Override
    public String toString() {
        return "Person2{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                '}';
    }

}
class paixu{

    //写一个排序算法
    public void bubblesort(Person2 persons[]){
        Person2 temp;
        for (int i = 0; i < persons.length - 1; i++) {
            for (int j = 0; j < persons.length - 1 -i; j++) {
                if(persons[j].getAge() <= persons[i].getAge()){
                    temp = persons[j];
                    persons[j] = persons[j+1];
                    persons[j+1] = temp;
                }
            }
        }
    }
    //定义方法,形参为Person类型,功能,调用学生的study和老师的teach方法
    //向下转型
    public void test(Person2 p){
        if(p instanceof Student1){//运行类型
            ((Student1) p).study();
        }
        else if(p instanceof Teacher1){
            ((Teacher1) p).teach();
        }
        else{
            System.out.println("do nothing");
        }
    }

}

 2.12 练习12 

this(“hello”)调用的本类的有参构造器,super和this只能用一个在句首,所以在b类中要注意,调用有参构造器之前要super()调用父类的无参

所以答案:A类,B类有参,C类有参,C类无参

 2.13 练习13

15.多态:方法或者对象具有多种形态,是OOP的第三大特征。建立在封装和继承的机制之上。

多态具体体现在1.方法的多态:(1)方法的重载体现多态(2)方法的重写 

2.对象的多态:(1)对象的编译类型和运行类型可以不一致,编译类型在定义的时候就定义不能改变

(2)对象的运行类型可以变化,可以通过getClass查看对象的运行类型

(3)编译类型看定义时的左边,运行类型看定义时的右边

(4)多态的向上转型本质:是父类的引用指向了子类的对象/语法:父类中所有满足权限的成员,不能调用子类的特有成员(比如猫的卓老鼠方法)

3.举例说明 :略

16.方法遵循动态绑定,而属性没有

1.当调用对象的方法时,该方法会和对象的内存地址/运行类型绑定,并且如果找不到,一直朝着父类去找

2.当调用对象的属性时没有动态绑定机制,遵守哪里声明哪里使用

补:继承的本质:当创建一个对象,建立一个查找关系

三、 房屋出租系统练习 

(界面,功能,数据)分层模式

 1.准备工具类

提问:为什么能不创建对象,直接调用方法呢,因为当一个方法是static的时候,就是一个静态方法,静态方法可以直接通过类名调用(如果方法和对象联系不大的时候就可用静态方法)

package houserent.utils;
/**
 工具类的作用:
 处理各种情况的用户输入,并且能够按照程序员的需求,得到用户的控制台输入。
 */

import java.util.*;
/**


 */
public class Utility {
    //静态属性。。。
    private static Scanner scanner = new Scanner(System.in);


    /**
     * 功能:读取键盘输入的一个菜单选项,值:1——5的范围
     * @return 1——5
     */
    public static char readMenuSelection() {
        char c;
        for (; ; ) {
            String str = readKeyBoard(1, false);//包含一个字符的字符串
            c = str.charAt(0);//将字符串转换成字符char类型
            if (c != '1' && c != '2' &&
                    c != '3' && c != '4' && c != '5') {
                System.out.print("选择错误,请重新输入:");
            } else break;
        }
        return c;
    }

    /**
     * 功能:读取键盘输入的一个字符
     * @return 一个字符
     */
    public static char readChar() {
        String str = readKeyBoard(1, false);//就是一个字符
        return str.charAt(0);
    }
    /**
     * 功能:读取键盘输入的一个字符,如果直接按回车,则返回指定的默认值;否则返回输入的那个字符
     * @param defaultValue 指定的默认值
     * @return 默认值或输入的字符
     */

    public static char readChar(char defaultValue) {
        String str = readKeyBoard(1, true);//要么是空字符串,要么是一个字符
        return (str.length() == 0) ? defaultValue : str.charAt(0);
    }

    /**
     * 功能:读取键盘输入的整型,长度小于2位
     * @return 整数
     */
    public static int readInt() {
        int n;
        for (; ; ) {
            String str = readKeyBoard(10, false);//一个整数,长度<=10位
            try {
                n = Integer.parseInt(str);//将字符串转换成整数
                break;
            } catch (NumberFormatException e) {
                System.out.print("数字输入错误,请重新输入:");
            }
        }
        return n;
    }
    /**
     * 功能:读取键盘输入的 整数或默认值,如果直接回车,则返回默认值,否则返回输入的整数
     * @param defaultValue 指定的默认值
     * @return 整数或默认值
     */
    public static int readInt(int defaultValue) {
        int n;
        for (; ; ) {
            String str = readKeyBoard(10, true);
            if (str.equals("")) {
                return defaultValue;
            }

            //异常处理...
            try {
                n = Integer.parseInt(str);
                break;
            } catch (NumberFormatException e) {
                System.out.print("数字输入错误,请重新输入:");
            }
        }
        return n;
    }

    /**
     * 功能:读取键盘输入的指定长度的字符串
     * @param limit 限制的长度
     * @return 指定长度的字符串
     */

    public static String readString(int limit) {
        return readKeyBoard(limit, false);
    }

    /**
     * 功能:读取键盘输入的指定长度的字符串或默认值,如果直接回车,返回默认值,否则返回字符串
     * @param limit 限制的长度
     * @param defaultValue 指定的默认值
     * @return 指定长度的字符串
     */

    public static String readString(int limit, String defaultValue) {
        String str = readKeyBoard(limit, true);
        return str.equals("")? defaultValue : str;
    }


    /**
     * 功能:读取键盘输入的确认选项,Y或N
     * 将小的功能,封装到一个方法中.
     * @return Y或N
     */
    public static char readConfirmSelection() {
        System.out.println("请输入你的选择(Y/N): 请小心选择");
        char c;
        for (; ; ) {//无限循环
            //在这里,将接受到字符,转成了大写字母
            //y => Y n=>N
            String str = readKeyBoard(1, false).toUpperCase();
            c = str.charAt(0);
            if (c == 'Y' || c == 'N') {
                break;
            } else {
                System.out.print("选择错误,请重新输入:");
            }
        }
        return c;
    }

    /**
     * 功能: 读取一个字符串
     * @param limit 读取的长度
     * @param blankReturn 如果为true ,表示 可以读空字符串。
     * 					  如果为false表示 不能读空字符串。
     *
     *	如果输入为空,或者输入大于limit的长度,就会提示重新输入。
     * @return
     */
    private static String readKeyBoard(int limit, boolean blankReturn) {

        //定义了字符串
        String line = "";

        //scanner.hasNextLine() 判断有没有下一行
        while (scanner.hasNextLine()) {
            line = scanner.nextLine();//读取这一行

            //如果line.length=0, 即用户没有输入任何内容,直接回车
            if (line.length() == 0) {
                if (blankReturn) return line;//如果blankReturn=true,可以返回空串
                else continue; //如果blankReturn=false,不接受空串,必须输入内容
            }

            //如果用户输入的内容大于了 limit,就提示重写输入
            //如果用户如的内容 >0 <= limit ,我就接受
            if (line.length() < 1 || line.length() > limit) {
                System.out.print("输入长度(不能大于" + limit + ")错误,请重新输入:");
                continue;
            }
            break;
        }

        return line;
    }
}

2.实现House类(看房屋列表的属性)

 除了定义属性,构造器和getter和setter方法,最好再重写一下tostring方法,根据这个房屋列表

//domain里面
package houserent.domain;

public class House {
    /**
     *House的对象表示一个房屋的信息
     */
    private int id;
    private String name;
    private String phone;
    private String address;
    private int rent;//租金
    private String state;//是否租出去状态

    //构造器和setter和getter方法

    public House(int id, String name, String phone, String address, int rent, String state) {
        this.id = id;
        this.name = name;
        this.phone = phone;
        this.address = address;
        this.rent = rent;
        this.state = state;
    }

    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 String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getRent() {
        return rent;
    }

    public void setRent(int rent) {
        this.rent = rent;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
    //为了方便输出对象信息,实现tostring

    @Override
    public String toString() {
        return id +
                '\t' + name +
                '\t' + phone +
                '\t' + address +
                '\t'+ rent +
                +'\t' +state
               ; 
    }
}

3.显示主菜单和退出软件

 首先是经典的菜单部分dowhile结构,设置一个loop为true退出以后置为fasle,然后设置一个key用switch结构不同情况,这里用了一个工具类

1)Houseview部分

//Houseview部分
package houserent.view;

import houserent.utils.Utility;

/*
*1.显示界面
*2.接收用户的输入
*3.调用HouseService完成对房屋信息的各种操作
* */
public class Houseview {
    //1.显示主菜单
    private boolean loop = true;
    private char key = ' ';
    public void mainMenu() {
        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("\t\t\t5.房屋列表");
            System.out.println("\t\t\t6.退出");
            System.out.println("请输入你的选择");
            key = Utility.readChar();
            switch (key){
                case '1':
                    System.out.println("新增");
                    break;
                case '2':
                    System.out.println("查找");
                    break;
                case '3':
                    System.out.println("删除");
                    break;
                case '4':
                    System.out.println("修改");
                    break;
                case '5':
                    System.out.println("列表");
                    break;
                case '6':
                    System.out.println("退出");
                    loop = false;
                    break;
            }
        }
        while(loop);
    }
}

2)主程序部分就是调用一下

直接创建一个匿名对象

//HouserentApp部分
package houserent;

import houserent.view.Houseview;

public class HouserentApp {
    public static void main(String[] args) {
        //创建Houseview对象并且显示主菜单,是整个程序的入口
        new Houseview().mainMenu();
        System.out.println("你退出了房屋出租系统");
    }
}

4.显示房屋列表

核心思想就是各司其职,首先是写service方法,通过一个list方法来显示所有的房屋信息

然后写view调用service的list方法输出,再遍历,遍历的时候要注意元素为空的情况 

//service
package houserent.service;
import houserent.domain.House;

/*
1.定义House数组,用来保存House对象
2.sevice响应HouseView的调用
3.完成对房屋信息的增删改查等操作crud
 */
public class HouseService {
    private House[] houses;//用来保存House对象
    public HouseService(int size){//是一个构造器
        houses = new House[size];
        //现在创建了以后,这个数组是空的,为了配合测试,给里面加一个元素、
        houses[0] = new House(1,"Jack","1100","中国青岛",1000,"未支付");
    }
    //写一个list方法,返回所有的房屋信息
    public House[] list(){
        return houses;
    }
}
//view
package houserent.view;

import houserent.domain.House;
import houserent.service.HouseService;
import houserent.utils.Utility;

/*
*1.显示界面
*2.接收用户的输入
*3.调用HouseService完成对房屋信息的各种操作
* */
public class Houseview {
    //1.显示主菜单
    private boolean loop = true;
    private char key = ' ';
    private HouseService houseService = new HouseService(10);
    public void listHouses(){
        System.out.println("==================房屋列表===================");
        System.out.println("编号\t\t房主\t\t电话\t\t地址\t\t月租\t\t状态(未出租/已出租)" );
        House[] houses = houseService.list();//已经得到了所有的房屋信息
        for (int i = 0; i < houses.length; i++) {
            if(houses[i] == null){
                break;
            }
            System.out.println(houses[i]);
        }
        System.out.println("==================房屋列表显示完毕===================");
        System.out.println();
    }
    public void mainMenu() {
        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("\t\t\t5.房屋列表");
            System.out.println("\t\t\t6.退出");
            System.out.println("请输入你的选择");
            key = Utility.readChar();
            switch (key){
                case '1':
                    System.out.println("新增");
                    break;
                case '2':
                    System.out.println("查找");
                    break;
                case '3':
                    System.out.println("删除");
                    break;
                case '4':
                    System.out.println("修改");
                    break;
                case '5':
                    listHouses();
                    break;
                case '6':
                    System.out.println("退出");
                    loop = false;
                    break;
            }
        }
        while(loop);
    }
}

5.添加房屋信息 

首先写view,值得注意的点是要创建一个新的House对象要注意id是在service中自动分配的

//view
package houserent.view;

import houserent.domain.House;
import houserent.service.HouseService;
import houserent.utils.Utility;

/*
*1.显示界面
*2.接收用户的输入
*3.调用HouseService完成对房屋信息的各种操作
* */
public class Houseview {
    //1.显示主菜单
    private boolean loop = true;
    private char key = ' ';
    private HouseService houseService = new HouseService(10);



    public void addHouses(){
        System.out.println("=================添加房屋===================");
        System.out.println("姓名:");
        String name = Utility.readString(8);
        System.out.println("电话:");
        String phone = Utility.readString(12);
        System.out.println("地址:");
        String address = Utility.readString(18);
        System.out.println("月租:");
        int rent = Utility.readInt();
        System.out.println("状态:");
        String state = Utility.readString(3);
        //创建一个新的House对象,注意id是系统分配的
        House newHouse =  new House(0, name, phone, address, rent, state);
        if(houseService.addHouse(newHouse)){
            System.out.println("==============添加房屋成功==========");
        }
        else{
            System.out.println("=============添加房屋失败===============");
        }
    }
    public void listHouses(){
        System.out.println("==================房屋列表===================");
        System.out.println("编号\t\t房主\t\t电话\t\t地址\t\t月租\t\t状态(未出租/已出租)" );
        House[] houses = houseService.list();//已经得到了所有的房屋信息
        for (int i = 0; i < houses.length; i++) {
            if(houses[i] == null){
                break;
            }
            System.out.println(houses[i]);
        }
        System.out.println("==================房屋列表显示完毕===================");
        System.out.println();
    }
    public void mainMenu() {
        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("\t\t\t5.房屋列表");
            System.out.println("\t\t\t6.退出");
            System.out.println("请输入你的选择");
            key = Utility.readChar();
            switch (key){
                case '1':
                    addHouses();
                    break;
                case '2':
                    System.out.println("查找");
                    break;
                case '3':
                    System.out.println("删除");
                    break;
                case '4':
                    System.out.println("修改");
                    break;
                case '5':
                    listHouses();
                    break;
                case '6':
                    System.out.println("退出");
                    loop = false;
                    break;
            }
        }
        while(loop);
    }
}

然后是Service层,添加add方法,其中要判断数组是否够满了,返回boolean值,设置两个新的值.第一个值的目的是把newHouse加入数组,第二个是为了搞一个自增的id,之所以分开是为了后边的删除

 private int houseNums = 1;//记录数组里有多少个对象
 private int idCounter = 1;//记录当前的id增长到哪个值了
package houserent.service;
import houserent.domain.House;
import sun.dc.pr.PRError;

/*
1.定义House数组,用来保存House对象
2.sevice响应HouseView的调用
3.完成对房屋信息的增删改查等操作crud
 */
public class HouseService {
    private House[] houses;//用来保存House对象
    private int houseNums = 1;//记录数组里有多少个对象
    private int idCounter = 1;//记录当前的id增长到哪个值了
    public HouseService(int size){//是一个构造器
        houses = new House[size];
        //现在创建了以后,这个数组是空的,为了配合测试,给里面加一个元素、
        houses[0] = new House(1,"Jack","1100","中国青岛",1000,"未支付");
    }
    //写一个list方法,返回所有的房屋信息
    public House[] list(){
        return houses;
    }
    //add方法,添加新的的对象,返回boolenan值
    public boolean addHouse(House newHouse){
        //注意数组是有限制的,p判断是否还能添加,暂时不考虑是否要扩容的问题
        if(houseNums  == houses.length){//不能再加了
            System.out.println("数组已满,不能再添加了");
            return false;
        }
        //把newHouse对象加入数组
        houses[houseNums++] = newHouse;
        //同时程序员要设计一个自增的id
        newHouse.setId(++idCounter);//这里不用同一个对象因为涉及到后边的删除
        return true;
    }
}

6.删除房屋信息  

删除房屋部分有几个需要注意的点:

1.在service部分,需要找到要删除的房屋的下标,这里注意这个下标和房屋编号是不一样的,所以要设置一个index来记录

 int index = -1;
        for (int i = 0; i < houseNums; i++) {
            if (delId == houses[i].getId()) {//要删除的房屋(id),是数组下标为i的元素、
                index = i;//用index记录一下
            }
        }
        if(index == -1){
            //说明delId在数组中不存在
            return false;
        }

2.如果找到了的话,怎么办,这里需要思考,思路就是遍历一下 往前覆盖,然后注意要释放最后一个元素

for (int i = index; i <houseNums -1 ; i++) {
                houses[i] = houses[i+1];
        }
        //这里要把最后一个制空并且数组容量减少一个
        houses[houseNums-1] = null;
        houseNums--;
        return true;

view部分

public void delHouse(){
        System.out.println("=================删除房屋===================");
        System.out.println("============请选择房屋编号(-1退出)==============");
        int detId = Utility.readInt();
        if(detId == -1){
            System.out.println("===========放弃删除房屋===================");
            return;
        }
        //注意该方法本身就有循环判断的逻辑,只能输出Y或者N
        char choice = Utility.readConfirmSelection();
        if(choice == 'Y'){//真的删除了
            if(houseService.delHouse(detId)){
                System.out.println("===========删除房屋成功===================");
            }
            else{
                System.out.println("===========删除房屋失败,编号不存在===================");
            }

        }
    }

service部分

 //写一个del方法,删除房屋信息
    public  boolean delHouse(int delId){
        //先找到删除的房屋信息对应的下标
        //这里一定要注意下标和房屋编号是不一样的
        int index = -1;
        for (int i = 0; i < houseNums; i++) {
            if (delId == houses[i].getId()) {//要删除的房屋(id),是数组下标为i的元素、
                index = i;//用index记录一下
            }
        }
        if(index == -1){
            //说明delId在数组中不存在
            return false;
        }
        //如果找到了,这里有点绕
        for (int i = index; i <houseNums -1 ; i++) {
                houses[i] = houses[i+1];
        }
        //这里要把最后一个制空并且数组容量减少一个
        houses[houseNums-1] = null;
        houseNums--;
        return true;

    }

7.`退出确认功能

用一下这个工具类即可 

    public void exit(){
        char c = Utility.readConfirmSelection();
        if(c == 'Y'){
            loop =  false;
        }
    }

 8.查找功能

//service
    //find方法,返回House对象或者一个空
    public House findById(int findId){
        //遍历
        for (int i = 0; i < houseNums; i++) {
            if(findId == houses[i].getId()){
                return houses[i];
            }
        }
        //否则返回一个空
        return null;
    }
//view
 public void findHouse(){
        System.out.println("=================查找房屋===================");
        System.out.println("=================请输入你要查找的id===================");
        int findId = Utility.readInt();
        //调用方法
        House house = houseService.findById(findId);
        if(house != null){
            System.out.println(house);
            System.out.println("=================查找成功===================");
        }
        else{
            System.out.println("=================查找的id不存在===================");
        }
    }

 9.修改功能

主要有几个注意的点,不需要再写一个service的方法,直接调用findByid 方法,在里面修改

在修改的过程要注意:

//值得注意的是,引用类型是存在堆里的,谁指向他都能直接修改。
//返回的是引用类型也就是数组中的元素 ,因此在后对house.setXX(),就会对HouseService中的houses数组进行修改

    public void updateHouse(){
        System.out.println("=================修改房屋===================");
        System.out.println("=================请选择修改的房屋编号(-1退出)===================");
        int UpdateId = Utility.readInt();
         if (UpdateId == -1){
             return;
         }
         House house = houseService.findById(UpdateId);
         if (house == null){
             System.out.println("=================你要修改的房屋信息不存在无法修改===================");
             return;
         }
        //值得注意的是,引用类型是存在堆里的,谁指向他都能直接修改。
        //返回的是引用类型也就是数组中的元素 ,因此在后对house.setXX(),就会对HouseService中的houses数组进行修改
        System.out.println("姓名("+ house.getName() +")");
         //读取修改的信息,有可能直接回车,如果是空的,那么就是不修改,如果不是空的那么就修改
         String name = Utility.readString(8,"");//这里如果用户直接回车的话,表示不修改信息
        if(!"".equals(name)){
                house.setName(name);
        }

        System.out.println("电话(" + house.getPhone() + ")");
        String phone = Utility.readString(12,"");
        if(!"".equals(phone)){
            house.setPhone(phone);
        }

        System.out.println("地址(" + house.getAddress() + ")");
        String address = Utility.readString(18,"");
        if(!"".equals(address)){
            house.setAddress(address);
        }

        System.out.println("租金(" + house.getRent() + ")");
        int rent = Utility.readInt(-1);
        if(rent != -1){
            house.setRent(rent);
        }

        System.out.println("状态(" + house.getState() + ")");
        String state = Utility.readString(18,"");
        if(!"".equals(address)){
            house.setState(state);
        }
        System.out.println("=================修改房屋信息成功===================");

    }

  • 35
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A_SHOWY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值