节练习)

Posted 朱呀朱-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了节练习)相关的知识,希望对你有一定的参考价值。

Java-Day-11

项目零钱通

  • 功能

    • 搭建菜单显示
    • 完成零钱明细
    • 完成收益入账
    • 完成消费功能
    • 实现退出完善,进行 y / n 确认
    • 判断入账、消费金额的合理性
  • 面向过程的代码

    package com.hspJava;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Scanner;
    
    public class SmallChangeSys 
        public static void main(String[] args)
            boolean flag = true;
            Scanner scanner = new Scanner(System.in);
            String key = "";
    
            String details = "-------------钱财服务明细-------------";
    
            // 收益
            double money = 0;
            double balance = 0;
            // 消费
            String note = "";
    
            // java.util,Date
            Date date = null;
            // 日期格式化
            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.println("请选择你所要做的操作: 1 ~ 4");
                key = scanner.next();
    
                switch (key)
                    case "1":
                        System.out.println(details);
                        break;
                    case "2":
                        System.out.println("收益入账金额:");
                        money = scanner.nextDouble();
                        // 找出不正确金额条件,提示后直接break ——> 一系列判断时,判不正确的更方便些,这样不仅可读性强,后期再添加不正确的情况时也更方便
                        if (money <= 0)
                            System.out.println("正确收入金额应大于0");
                            break;
                        
                        balance += money;
                        // 获取当前日期
                        date = new Date();
                        details += "\\n收益入账\\t+" + money + "\\t" + sdf.format(date) + "\\t" + balance;
                        break;
                    case "3":
                        System.out.println("消费金额:");
                        money = scanner.nextInt();
                        if (money <= 0 || money > balance)
                            System.out.println("消费金额不能为0或者大于余额");
                        
                        System.out.println("消费情况:");
                        note = scanner.next();
    
                        balance -= money;
                        date = new Date();
    
                        details += "\\n" + note + "\\t-" + money + "\\t" + sdf.format(date) + "\\t" + balance;
    
                        break;
                    case "4":
                        String choice = "";
                        while(true)
                            System.out.println("你确定要退出吗? y/n");
                            choice = scanner.next();
                            // 一段代码实现一个小功能,这样后期改善、拓展更方便更改,例:除了y、n外再加一个待定...
                            // 尽量不要混合在一起,这样代码耦合性低,提高可读性
                            if ("y".equals(choice) || "n".equals(choice))
                                break;
                            
                        
                        if (choice.equals("y"))
                            flag = false;
                        
                        // n 就是不退出,就是不做处理
                        break;
                    default:
                        System.out.println("选择有误,请重新选择");
                
    
            while(flag);
        
    
    
  • 修改为面向对象 OOP

    • SmallChangeSysOOP:完成各个功能
    // SmallChangeSysOOP:
    package com.hspJava.OOP;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Scanner;
    
    public class SmallChangeSysOOP 
        boolean flag = true;
        Scanner scanner = new Scanner(System.in);
        String key = "";
        String details = "-------------钱财服务明细-------------";
        // 收益
        double money = 0;
        double balance = 0;
        // 消费
        String note = "";
        // java.util,Date
        Date date = null;
        // 日期格式化
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    
    
        // 被调用的主方法:菜单
        public void mainMenu()
            do
                System.out.println("========软件钱财服务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 (key)
                    case "1":
                        this.detail();
                        break;
                    case "2":
                        this.income();
                        break;
                    case "3":
                        this.pay();
                        break;
                    case "4":
                        this.exit();
                        // n 就是不退出,就是不做处理
                        break;
                    default:
                        System.out.println("选择有误,请重新选择");
                
            while(flag);
        
    
    //    完成零钱明细
        public void detail()
            System.out.println(details);
    //        此处采用简单的直接拼接的方法放进details里
        
    
    //    完成收益入账
        public void income()
            System.out.println("收益入账金额:");
            money = scanner.nextDouble();
            // 找出不正确金额条件,提示后直接break ——> 一系列判断时,判不正确的更方便些,这样不仅可读性强,后期再添加不正确的情况时也更方便
            if (money <= 0)
                System.out.println("正确收入金额应大于0");
    //            break; 在面向对象时选择退出方法
                return;
            
            balance += money;
            // 获取当前日期
            date = new Date();
            details += "\\n收益入账\\t+" + money + "\\t" + sdf.format(date) + "\\t" + balance;
        
    
    //    消费
        public void pay()
            System.out.println("消费金额:");
            money = scanner.nextInt();
            if (money <= 0 || money > balance)
                System.out.println("消费金额不能为0或者大于余额");
                return;
            
            System.out.println("消费情况:");
            note = scanner.next();
    
            balance -= money;
            date = new Date();
    
            details += "\\n" + note + "\\t-" + money + "\\t" + sdf.format(date) + "\\t" + balance;
        
    
    //    退出
        public void exit()
            String choice = "";
            while(true)
                System.out.println("你确定要退出吗? y/n");
                choice = scanner.next();
                // 一段代码实现一个小功能,这样后期改善、拓展更方便更改,例:除了y、n外再加一个待定...
                // 尽量不要混合在一起,这样代码耦合性低,提高可读性
                if ("y".equals(choice) || "n".equals(choice))
                    break;
                
            
            if (choice.equals("y"))
                flag = false;
            
        
    
    
    
    • SmallChangeSysApp:调用相关方法完成功能
    // 在这里直接调用SmallChangeSysOOP对象,显示主菜单即可
    public class SmallChangeSysApp 
        public static void main(String[] args) 
            new SmallChangeSysOOP().mainMenu();
        
    
    
    
    • 此面向对象的方式,不仅可以供方法给他人使用,在拓展优化功能时可以更方便写入

章节练习

  • Person 数组存三个对象,按对象年龄从大到小冒泡排序

    // main
    Person[] persons = new Person[3];
    persons[0] = new Person(...);
    persons[1] = new Person(...);
    persons[2] = new Person(...);
    
    for(int i = 0; i < persons.length - 1; i++) // 外部
        for(int j = 0; j < person.lenth - 1 - i, j++) // 内部每次定最后一个
        	System.out.println();
        	// 用于交换的临时变量
        	Person tmp = null;
        	if(persons[i].getAge() < person[i + 1].getAge())
            	tmp = person[i];
            	person[i] = person[i + 1];
            	person[i + 1] = tmp;
        	
        
    
    
    • 若是看名字长度,就persons[i].getName().length
  • 编写对象时,若是姓名、固定工资等可以写进构造器中,但若是奖金等可能会变化的值就最好不要写进构造器里,而是用 get、set 方法,于需要时 get 获取,main 里 set 存入

    // 若是继承了父类的day属性,在计算工资时就可以在子类中使用get方法
    public void printSal()
        System.out.println("管理层" + getname() + "的工资是" + (bonus + getDaySal() * getGrade()) + "。");
    
    
    // 若是没有特殊加奖金等要求,就可以直接继承父类方法,无需像上述管理层那样重写
    public void printSal()
        super.printSal();
    
    
  • 设计父类——员工类,子类:农民类 ( Peasant ),教师类 ( Teaher ),科学家类 ( Scientist )

    • 其中农民只有基本工资
    • 教师除了基本工资外,还有课酬 ( 元/天 )
    • 科学家除基本工资外还有年终奖
    • 编写一个测试类,将各种类型的员工的全年工资打印出来
    // 父类——员工类
    public class Employee 
        private String name;
        private double sal;
    //    带薪月份:salMonth,这里假设是12个月
        private int salMonth = 12;
    
        public Employee(String name, double sal) 
            this.name = name;
            this.sal = sal;
        
        public void printSal()
            System.out.println(name + "的年工资是:" + (sal * salMonth));
        
        public double printSaltest()
            return sal * salMonth;
        
        // 此处省略所有私有属性的get、set方法
    
    
    // 农民类
    public class Peasant extends Employee
    
        public Peasant(String name, double sal) 
            super(name, sal);
        
        public void printSal()
            System.out.print("农民");
            super.printSal();
        
    
    
    // 教师类
    public class Teacher extends Employee
        private int classDays; // 一天课时
        private double classSal; // 课时费
    
        public Teacher(String name, double sal) 
            super(name, sal);
        
        public void printSal() 
            System.out.print("老师");
            System.out.println(getName() + "的年工资是:" + (getSal() * getSalMonth() + classSal * classDays));
        
        // 此处省略私有属性的get、set方法
    
    
    // 科学家类
    public class Scientist extends Employee
        private double bonus;
    
        public Scientist(String name, double sal) 
            super(name, sal);
        
        @Override
        public void printSal() 
            System.out.println("科学家");
            System.out.println("*****用(getSal() * getSalMonth() + bonus)");
            System.out.println(getName() + "的年工资是:" + (getSal() * getSalMonth() + bonus));
            System.out.println("*****用(getSal() * getSalMonth() + getBonus())");
            System.out.println(getName() + "的年工资是:" + (getSal() * getSalMonth() + getBonus()));
            System.out.println("*****用(super.printSaltest() + bonus),前提是父类有一个方法printSaltest()是返回double类型的纯工资计算式结果");
            System.out.println(getName() + "的年工资是:" + super.printSaltest() + bonus);
            System.out.println("*****因为前面有字符串,所以上面输出的是字符串拼接后加bonus,所以要像下面括号括起来先");
            System.out.println(getName() + "的年工资是:" + (super.printSaltest() + bonus));
        
        
        // 私有属性的get、set方法
        public double getBonus() 
            return bonus;
        
    
        public void setBonus(double bonus) 
            this.bonus = bonus;
        
    
    
    // main所在
    public class SalTest 
        public static void main(String[] args) 
            Peasant p1 = new Peasant("小一", 1000);
    //        可随时更改带薪月份,从而更改了年薪
    //        p1.setSalMonth(10);
            p1.printSal();
    
            Teacher t1 = new Teacher("小二", 2000);
            t1.setClassDays(365);
            t1.setClassSal(100);
            t1.printSal();
    
            Scientist s1 = new Scientist("小四", 2000);
            s1.setBonus(5);
            s1.printSal();
        
    
    
    /* 输出为
    农民小一的年工资是:12000.0
    老师小二的年工资是:60500.0
    科学家
    *****用(getSal() * getSalMonth() + bonus)
    小四的年工资是:24005.0
    *****用(getSal() * getSalMonth() + getBonus())
    小四的年工资是:24005.0
    *****用(super.printSaltest() + bonus),前提是父类有一个方法printSaltest()是返回double类型的纯工资计算式结果
    小四的年工资是:24000.05.0
    *****因为前面有字符串,所以上面输出的是字符串拼接后加bonus,所以要像下面括号括起来先
    小四的年工资是:24005.0
    
    Process finished with exit code 0
    */
    
    
  • 勿混淆 this、super

    • this:当前对象开始,向上到父类、超类 ...

    • super:子类中访问的父类对象开始,向上访问到超类 ...

    • 不管 this 还是 super 都要遵守访问权限、就近原则

    class Test
        String name = "ZHANG";
        Test(String name)
            this.name = name;
        
    
    
    class Demo extends Test
        String name = "ZHU";
        Demo(String s)
            super(s);
        
        public void test()
            System.out.print(super.name);
            System.out.print(this.name);
        
        public static void main(String[] args)
            new Demo("jojo").test();
            // 输出为 jojo ZHU
        
    
    
  • 银行存款取款 — BankAccount,

    • BankAccount 基础上扩展,建一个新类 CheckingAccount,每次存、取款都要加一块钱的手续费
    • BankAccount 基础上扩展,建一个新类 SavingsAccount,每个月都有利息产生,并且每月三次免手续费的存或取款
    // 父类
    public class BankAccout 
        private double balance;
        public BankAccout(double initiaBalance)
            this.balance = initiaBalance;
        
    //    存款
        public void deposit(double amount)
            balance += amount;
        
    //    取款
        public void withdraw(double amount)
            balance -= amount;
        
    // set、get 方法 
    
    
    // 子CheckingAccount
    public class CheckingAccount extends BankAccout
    
        public CheckingAccount(double initiaBalance) 
            super(initiaBalance);
        
        public void deposit(double amount)
    //        这样就无需重写,巧用父类
            super.deposit(amount - 1);
        
        public void withdraw(double amount)
    //        父类减钱减的是amount,所以这里是加1
            super.withdraw(amount + 1);
        
    
    
    // 子SavingsAccount
    public class SavingsAccount extends BankAccout
        private int count = 3;
        private double rate = 0.1;
    
        public SavingsAccount(double initiaBalance) 
            super(initiaBalance);
        
        
        @Override
        public void deposit(double amount) 
            //        判断是否还可以免手续费
            if (count > 0)
                super.deposit(amount);
             else 
                super.deposit(amount - 1);
            
            count--;
        
    
        @Override
        public void withdraw(double amount) 
            if (count > 0)
                super.withdraw(amount);
             else 
                super.withdraw(amount + 1);
            
            count--;
        
    
        //    每个月初,统计上个月的利息,同时将count=3
        public void earnMonthlyInterest()
            count = 3;
            super.deposit(getBalance() * rate);
        
    // set、get 方法 
    
    
    // test测试
    public class SalTest 
        public static void main(String[] args) 
            CheckingAccount checkingAccount = new CheckingAccount(1000);
            checkingAccount.deposit(10);
            System.out.println(checkingAccount.getBalance()); // 1009.0
    
            SavingsAccount savingsAccount = new SavingsAccount(100);
            savingsAccount.deposit(10);
            savingsAccount.deposit(10);
            savingsAccount.deposit(10);
            System.out.println(savingsAccount.getBalance()); // 130
            savingsAccount.deposit(10);
            System.out.println(savingsAccount.getBalance()); // 130 + 10 - 1 = 139
    //        假设月初了
            savingsAccount.earnMonthlyInterest();
            System.out.println(savingsAccount.getBalance()); // 139 + 139 * 0.1 = 152.9
        
    
    
  • 向上转型和向下转型

    class Person
        public void sing()
            System.out.println("person sing");
        
        public void dance()
            System.out.println("person dance");
        
    
    
    class Student extends Person
        public void sing()
            System.out.println("Student sing");
        
        public void rap()
            System.out.println("Student rap");
        
    
    
    // 向下转型:编译类型是p,
    Person p = new Student();
    p.sing(); // 调用就动态绑定机制,运行是从子类开始找实现内容——Student sing
    p.dance(); // 子类没有再去父类找——person dance
    // p.rap 用不了,只有编译类型的方法能用
    
    //向下转型:把指向子类对象的父类引用,转成指向子类的子类引用,编译类型变成子类,此时一个指向堆的p一个s
    Student s = (Student)p;
    s.sing(); // Student sing
    s.rap(); // Student rap
    s.dance(); // person dance
    
  • 定义方法,形参为父类 Person 类型,功能:调用 Student 的 study 方法或者老师 Teacher 的 teach 方法

    public void test(Person p) 
        if(p instanceof Student) 
            ((Student) p).study();
         else if(p instanceof Teacher) 
            ((Teacher) p).teach();
         else 
            System...
        
    
    
  • 区分 == 与 equals

    名称 概念 用于基本数据类型 用于引用类型
    == 比较运算符 可以,判断值是否相等 可以,判断是否是同一个对象
    equals Object 类的方法,Java 类都可以使用 不可以 可以,默认判断两个对象是否相等,但是子类往往重写为比较对象的属性是否相同
  • 多态:方法或对象具有多种状态,是 OOP 的第三大特征,是建立在封装和继承基础之上的

    • 体现
      • 方法:重载、重写
      • 对象:编译类型可以与运行类型不同,编译类型不可改变,但运行类型可以变化,可以用 .getClass() 来查看运行类型
    • 向上转型:父 = new 子;超 = new 父 / 子 ;超 = 父 / 子切换
    • 向下转型:( 父 = new 子 后 ) 子 = ( 子 ) 父

1.5.2-1.6 节练习

 1 /*练习 1.23*/ 
 2 #include <iostream>
 3 #include "Sales_item.h" 
 4 
 5 int main(void)
 6 {
 7     Sales_item total, trans;
 8     std::cout << "请输入销售记录" << std::endl;
 9     if(std::cin >> total)
10 {
11     int n = 1;
12     while(std::cin >> trans)
13     {
14         if(compareIsbn(total,trans))
15           ++n;
16         else
17         {
18             std::cout << total << "的销售记录条数为:" << n <<std::endl;
19             total = trans;
20             n = 1; 
21         }
22     }
23         std::cout << total << "的销售条数是:" << std::endl;    
24 }
25     return 0;
26 }

这个是模仿开头的计数器程序写的

1.24自己去试数据就行

1.25是书上的程序

技术分享图片
 1 #include <iostream>
 2 #include "Sales_item.h"
 3 
 4 int main()
 5 {
 6     Sales_item total;
 7     if(std::cin >> total){
 8         Sales_item trans;
 9         while(std::cin >> trans){
10         if(total.isbn() == trans.isbn())
11             total += trans;
12         else{
13             std::cout << total << std::endl;
14             total = trans;
15         }
16     }
17     std::cout << total << std::endl;
18     }else{
19         std::cerr << "No data?!" << std::endl;
20         return -1;
21     }
22     return 0;
23 }
View Code

 

以上是关于节练习)的主要内容,如果未能解决你的问题,请参考以下文章

2.5.2节练习

循环小练习

循环小练习

1.5.2-1.6 节练习

练习5.6.3节

HihoCoder1637 : 逃离单身节([Offer收割]编程练习赛36)(模拟)