一、零钱通项目练习
深刻理解面向对象编程的好处,包括复用性等等。
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
此题目综合性较强需要注意的是以下几点
- 在(7)做多态数组的是时候,排序使用经典的冒泡排序
- 在(8)中做特殊功能的时候,使用多态的向下转型 ,其他的都不难
- 输出的时候重写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.准备工具类![](https://i-blog.csdnimg.cn/direct/c8c31e78d0a54f89841f7d961fe9930d.png)
提问:为什么能不创建对象,直接调用方法呢,因为当一个方法是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.查找功能![](https://i-blog.csdnimg.cn/direct/ae254b7c68f94e999a11054948d51b66.png)
//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("=================修改房屋信息成功===================");
}