OOP第一次作业总结

 一、前言

   大一上学习完C语言程序设计课程后,第一次接触Java语言和面向对象,对Java语言的语法还尚不熟悉,前两次训练集主要训练了Java的语法,从第三次训练集开始训练类的设计和使用,前两周还在适应期,代码不规范,可读性很差,后面随着训练,自认为可读性应该强了不少。

   训练集01总共12道题,说实话对于才刚开始学习Java语法的我来说,题量比较大,一开始也总编译错误,对Java语法完全不熟悉在简单的题上浪费了许多时间,但其实训练集01的题难度不算很大,除了那道GPS数据处理的题,训练的知识点其实都是选择、循环、数组、字符串等较基础的Java语法。因为刚从C/C++转入Java,正在适应期,对IDE工具的使用也不够老练,在PTA上编译了许多次,总因为语法错误编译错误。现在回头再看一遍题目,难度其实并不高。

         训练集02总共9道题,题量一般,主要训练逻辑思维,大部分是计算题,此时已经过训练集01的训练,难度较低,当然除了最后一道题。最后一道题“求下一天”有点难度,这道题也是我花费时间最多的一天,题目给了方法名和需求,需要自己写方法,而因为有闰年平年大月小月,有很多细节需要照顾到。

         训练集03虽然只有4道题,但是难度较高,涉及到了类的设计,这次训练集花费的时间最多。接下来会对其重点分析。

二、设计与分析

1.创建圆形类          

     编写一个圆形类Circle,一个私有实型属性半径,要求写出带参数构造方法、无参构造方法、属性的getter、setter方法以及求面积、输出数据等方法,具体格式见输入、输出样例。

以下为我的代码:

 1 import java.util.*;
 2 public class Main{
 3     public static void main(String[] args){
 4         Circle c=new Circle();
 5         Scanner in=new Scanner(System.in);
 6         double r1 = in.nextDouble();
 7         c.setRadius(r1);
 8         c.prin();
 9     }
10 }
11 
12 class Circle{
13     private double radius;
14     public void setRadius(double r){
15             radius=r;
16         
17     }
18     public double getRadius(){
19         return radius;
20             
21     }
22     public double getArea(){
23         return Math.PI*radius*radius;
24     }
25     public void prin(){
26         if(radius<0){
27             System.out.print("Wrong Format");
28         }
29         else{
30             System.out.printf("The circle's radius is:%.2f\n",getRadius());
31             System.out.printf("The circle's area is:%.2f\n",getArea());
32         }
33         
34     }
35 }

类图如下:

第一道题非常简单,只是为学习类的设计开了个头。但是我还是没写好,应该再在Circle类里面加上

public Circle{
}
public Circle(double radius){
    radius=this.radius;
}

并且加上this关键字会更加规范。

2.创建账户类Account

设计一个名称为Account的类,具体包括:

  • id:账号,私有属性,整型,默认值为0;
  • balance:余额,私有属性,实型,默认值为0;
  • annualInterestRate:当前利率,私有属性,实型,默认值为0,假设所有帐户均有相同的利率;
  • dateCreated:账户开户时间,私有属性,LocalDate类型,默认为2020年7月31日;
  • 一个能创建默认账户的无参构造方法;
  • 一个能创建带特定id和初始余额的账户的构造方法;
  • id、balance、annualInterstRate的getter及setter方法;
  • dateCreated的getter方法;
  • 一个名为getMonthlyInterestRate()的方法返回月利率(月利率计算公式:余额*(年利率/1200));
  • 一个名为withDraw的方法从账户提取特定数额,当提取数额大于余额或为负数系统返回WithDraw Amount Wrong提示;
  • 一个名为deposit的方法向账户存储特定数额,当存储数额大于20000元或为负数系统返回Deposit Amount Wrong提示。

编写一个测试程序:

  1. 创建一个账户,其账户id、余额及利率分别有键盘输入,账户开户时间取系统当前时间;
  2. 输入取钱金额,系统进行取钱操作,如果取钱金额有误,则输出提示信息后系统继续运行;
  3. 输入存钱金额,系统进行存钱操作,如果存钱金额有误,则输出提示信息后系统继续运行;

系统输出,以如下格式分别输出该账户余额、月利息以及开户日期(输出实型数均保留两位小数)

以下为我的代码:

 1 import java.util.Scanner;
 2 import java.time.LocalDate;
 3 
 4 public class Main{
 5     static class Account{
 6         private int id;
 7         private double balance;
 8         private double annuallnterestRate;
 9         private LocalDate dateCreated=LocalDate.of(2020,7,31);
10         public Account(){
11             
12         }
13         public Account(int id,double balance){
14             this.id=id;
15             this.balance=balance;
16         }
17         public int getId(){
18             return this.id;
19         }
20         public double getAnnuallnterestRate(){
21             return this.annuallnterestRate;
22         }
23         public void setAnnuallnterestRate(double annuallnterestRate){
24             this.annuallnterestRate=annuallnterestRate;
25         }
26         public LocalDate getDateCreated(){
27              return this.dateCreated;
28         }
29         public double getMonthlyInterestRate(){
30             return this.balance*(this.annuallnterestRate/1200);
31         }
32         public void withDraw(double amount){
33             if(amount>balance||amount<0){
34                 System.out.println("WithDraw Amount Wrong");
35             }
36             else
37                 this.balance-=amount;
38         }
39         public void deposit(double amount){
40             if(amount>20000||amount<0){
41                 System.out.println("Deposit Amount Wrong");
42             }
43             else
44                 this.balance+=amount;
45         }
46         public double getBalance(){
47             return this.balance;
48         }
49     }
50     public static void main(String[] args){
51         Scanner in=new Scanner(System.in);
52         int id=in.nextInt();
53         double balance=in.nextDouble();
54         Account acc=new Account(id,balance);
55         
56         double annuallnterestRate=in.nextDouble();
57         acc.getAnnuallnterestRate();
58         acc.setAnnuallnterestRate(annuallnterestRate);
59 
60         LocalDate date =LocalDate.now();
61         
62         double tiAmount=in.nextDouble();
63         acc.withDraw(tiAmount);
64         double cunAmount=in.nextDouble();
65         acc.deposit(cunAmount);
66         
67         System.out.printf("The Account'balance:%.2f\n",acc.getBalance());
68         acc.getAnnuallnterestRate();
69         LocalDate dateCreated=acc.getDateCreated();
70         System.out.printf("The Monthly interest:%.2f\n",acc.getMonthlyInterestRate());
71         System.out.printf("The Account'dateCreated:%d-%02d-%d",dateCreated.getYear(),dateCreated.getMonthValue(),dateCreated.getDayOfMonth());
72     }
73 }

这道题已经给了很清楚的方法,这道题照着需求写就可以了。首先定义属性,其中存储了账户id、余额、年利率和开户日期等信息,并提供了存款、取款、计算月利率等功能。在主函数中,通过Scanner获取用户输入的账户信息,包括id、余额、年利率,以及取款和存款金额。最终输出账户余额、月利率、开户日期等信息。使用面向对象的编程思想,将账户信息封装在Account类中,并通过方法来提供各种操作。我还使用了局部类(LocalDate)以完成 账户开户时间取系统当前时间 的功能实现。

类图如下:

 

3.定义日期类

定义一个类Date,包含三个私有属性年(year)、月(month)、日(day),均为整型数,其中:年份的合法取值范围为[1900,2000] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。

要求类图如下:

 

以下为我的代码:

import java.util.Scanner;

public class Main{
    static class Date{
        private int year;
        public int getYear(){
            return this.year;
        }
        public void setYear(int year){
            if(year>=1900&&year<=2000){
                this.year=year;
            }

} private int month; public int getMonth(){ return this.month; } public void setMonth(int month){ if(month>=1&&month<=12){ this.month=month; } } private int day; public int getDay(){ return this.day; } public void setDay(int day){ if(day>=1&&day<=31){ this.day=day; } } public Date(){ } public Date(int year,int month,int day){ this.year=year; this.month=month; this.day=day; } private int[] mon_maxnum=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31}; public boolean isLeapYear(int year){ if(year%4==0&&year%100!=0||year%400==0){ return true; } else{ return false; } } public boolean checkInputValidity(){ if(this.year<1900||this.year>2000||this.month<1||this.month>12||this.day<1||this.day>31) return false; else if(this.month==2){ if(this.year%4==0&&this.year%100!=0||this.year%400==0){ if(this.day>29) return false; else return true; } else{ if(this.day>28) return false; else return true; } } else if(this.day>mon_maxnum[this.month]) return false; else return true; } public void getNextDate(){ if(this.year%4==0&&this.year%100!=0||this.year%400==0){ mon_maxnum[2]=29; if(this.month==12&&this.day==31){ if(this.year==2000) System.out.print("Date Format is Wrong"); else if(this.year!=2000) System.out.print("Next day is:"+(this.year+1)+"-1-1"); } else if(this.month!=12 && this.day==mon_maxnum[this.month]){ System.out.print("Next day is:"+this.year+"-"+(this.month+1)+"-1"); } else{ System.out.print("Next day is:"+this.year+"-"+this.month+"-"+(this.day+1)); } } else{ if(this.month==12&&this.day==31){ if(this.year==2000) System.out.print("Date Format is Wrong"); else if(this.year!=2000) System.out.print("Next day is:"+(this.year+1)+"-1-1"); } else if(this.month!=12 && this.day==mon_maxnum[this.month]){ System.out.print("Next day is:"+this.year+"-"+(this.month+1)+"-1"); } else{ System.out.print("Next day is:"+this.year+"-"+this.month+"-"+(this.day+1)); } } } } public static void main(String[] args){ Scanner in=new Scanner(System.in); Date d=new Date(); int year=in.nextInt(); int month=in.nextInt(); int day=in.nextInt(); d.getYear(); d.setYear(year); d.getMonth(); d.setMonth(month); d.getDay(); d.setDay(day); if(d.checkInputValidity()){ d.getNextDate(); } else{ System.out.print("Date Format is Wrong"); } } }

Date类包含了私有的年、月、日成员变量(year, month, day),以及对应的get和set方法。其中,set方法采用了参数检查机制,如果输入的年份、月份或日份不在合法范围内,就不会进行传参。Date类还包含了一个无参构造函数和一个有参构造函数,分别可以创建空的或指定日期的日期对象。另外,根据给出类图定义了一个私有成员数组mon_maxnum,用于存储每个月份的最大天数。 Date类还包含了:一个检查日期输入是否合法的方法checkInputValidity(),通过检查年、月、日是否在合法范围内来判断输入是否正确,这个方法的实现依赖于之前的日期成员变量和set方法;一个判断当前年份是否为闰年的方法isLeapYear(),基于闰年的定义来进行实现,这个方法的实现比较简单,只需要分别对年份取余并进行判断即可;一个获取下一个日期的方法getNextDate(),通过判断年份是否为闰年,月份是否是12月,日份是否为最大天数等条件,进行计算和输出下一个日期信息。

4.日期类设计

参考题目3和日期相关的程序,设计一个类DateUtil,该类有三个私有属性year、month、day(均为整型数),其中,year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 除了创建该类的构造方法、属性的getter及setter方法外,需要编写如下方法:

public boolean checkInputValidity();//检测输入的年、月、日是否合法
public boolean isLeapYear(int year);//判断year是否为闰年
public DateUtil getNextNDays(int n);//取得year-month-day的下n天日期
public DateUtil getPreviousNDays(int n);//取得year-month-day的前n天日期
public boolean compareDates(DateUtil date);//比较当前日期与date的大小(先后)
public boolean equalTwoDates(DateUtil date);//判断两个日期是否相等
public int getDaysofDates(DateUtil date);//求当前日期与date之间相差的天数
public String showDate();//以“year-month-day”格式返回日期值

应用程序共测试三个功能:

  1. 求下n天
  2. 求前n天
  3. 求两个日期相差的天数

题目已给出主方法:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int year = 0;
        int month = 0;
        int day = 0;

        int choice = input.nextInt();

        if (choice == 1) { // test getNextNDays method
            int m = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            DateUtil date = new DateUtil(year, month, day);

            if (!date.checkInputValidity()) {
                System.out.println("Wrong Format");
                System.exit(0);
            }

            m = input.nextInt();

            if (m < 0) {
                System.out.println("Wrong Format");
                System.exit(0);
            }

            System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
            System.out.println(date.getNextNDays(m).showDate());
        } else if (choice == 2) { // test getPreviousNDays method
            int n = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            DateUtil date = new DateUtil(year, month, day);

            if (!date.checkInputValidity()) {
                System.out.println("Wrong Format");
                System.exit(0);
            }

            n = input.nextInt();

            if (n < 0) {
                System.out.println("Wrong Format");
                System.exit(0);
            }

            System.out.print(
                    date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
            System.out.println(date.getPreviousNDays(n).showDate());
        } else if (choice == 3) {    //test getDaysofDates method
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            int anotherYear = Integer.parseInt(input.next());
            int anotherMonth = Integer.parseInt(input.next());
            int anotherDay = Integer.parseInt(input.next());

            DateUtil fromDate = new DateUtil(year, month, day);
            DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);

            if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
                System.out.println("The days between " + fromDate.showDate() + 
                        " and " + toDate.showDate() + " are:"
                        + fromDate.getDaysofDates(toDate));
            } else {
                System.out.println("Wrong Format");
                System.exit(0);
            }
        }
        else{
            System.out.println("Wrong Format");
            System.exit(0);
        }        
    }
}

以下为我设计的类图:

DateUtil类的代码如下:

    static class DateUtil {
        private int year;
        public int getYear() {
            return year;
        }
        public void setYear(int year) {
            this.year = year;
        }
        
        private int month;
        public int getMonth() {
            return month;
        }
        public void setMonth(int month) {
            this.month = month;
        }
        
        private int day;
        public int getDay() {
            return day;
        }
        public void setDay(int day) {
            this.day = day;
        }
        
        private int[] mon_maxnum=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
        
        public DateUtil(){
            
        }
        public DateUtil(int year, int month, int day) {
            this.year = year;
            this.month = month;
            this.day = day;
        }
        
        public boolean checkInputValidity() {//检测输入的年、月、日是否合法
            if (this.year < 1820 || this.year > 2020 || this.month < 1 || this.month > 12 || this.day < 1 || this.day > 31)
                return false;
            else if (this.month == 2) {
                if (this.year % 4 == 0 && this.year % 100 != 0 || this.year % 400 == 0) {
                    if (this.day > 29)
                        return false;
                    else
                        return true;
                } else {
                    if (this.day > 28)
                        return false;
                    else
                        return true;
                }
            } else if (this.day > mon_maxnum[this.month])
                return false;
            else
                return true;
        }
        public boolean isLeapYear(int year) {//判断year是否为闰年
            if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
                return true;
            }
            return false;
        }
        public DateUtil getNextDay(){
            
            int newYear = 0;
            int newMonth = 0;
            int newDay = 0;
            if(this.year%4==0&&this.year%100!=0||this.year%400==0){
                mon_maxnum[2]=29;
                if(this.month==12&&this.day==31){
                    if(this.year!=2020){
                        newYear =this.year + 1;
                        newMonth = 1;
                        newDay = 1;
                    }
                    
                }
                else if(this.month!=12 && this.day==mon_maxnum[this.month]){
                    newYear = this.year;
                    newMonth = this.month + 1;
                    newDay = 1;
                }
                else{
                    newYear = this.year;
                    newMonth = this.month;
                    newDay = this.day + 1;
                }
            }
            else{
                if(this.month==12&&this.day==31){
                    if(this.year==2020)
                        System.out.print("Wrong Format");
                    else if(this.year!=2020){
                        newYear = this.year + 1;
                        newMonth = 1;
                        newDay = 1;
                    }
                        
                }
                else if(this.month!=12 && this.day==mon_maxnum[this.month]){
                    newYear = this.year;
                    newMonth = this.month + 1;
                    newDay = 1;
                }
                else{
                    newYear = this.year;
                    newMonth = this.month;
                    newDay = this.day + 1;
                }
            }
            return new DateUtil(newYear, newMonth, newDay);
        }
        public DateUtil getNextNDays(int n) {//取得year-month-day的下n天日期
            DateUtil newDate = new DateUtil(year, month, day);
            int newYear = this.year;
            int newMonth = this.month;
            int newDay = this.day;
            for (int i = 0; i < n; i++) {
                //newDate = newDate.getNextDay();
                
            if(newYear%4==0&&newYear%100!=0||newYear%400==0){
                mon_maxnum[2]=29;
                if(newMonth==12&&newDay==31){
                        newYear =newYear + 1;
                        newMonth = 1;
                        newDay = 1;
                    
                    
                }
                else if(newMonth!=12 && newDay==mon_maxnum[newMonth]){
                    newMonth = newMonth + 1;
                    newDay = 1;
                }
                else{
                    newDay = newDay + 1;
                }
            }
            else{
                mon_maxnum[2]=28;
                if(newMonth==12&&newDay==31){
                        newYear = newYear + 1;
                        newMonth = 1;
                        newDay = 1;
                    
                        
                }
                else if(newMonth!=12 && newDay==mon_maxnum[newMonth]){
                    newMonth = newMonth + 1;
                    newDay = 1;
                }
                else{
                    newDay = newDay + 1;
                }
            }
            }
            return new DateUtil(newYear, newMonth, newDay);
        }
        public DateUtil getPreviousDay(){
            int newYear = 0;
            int newMonth = 0;
            int newDay = 0;
            if(this.day==1 && (this.month==2 || this.month==4 || this.month==6 || this.month==8 || this.month==9 || this.month==11 || this.month==1)){
                if(this.month == 1){
                    newYear = this.year - 1;
                    newMonth = 12;
                    newDay = 31;
                }
                else{
                    newYear = this.year;
                    newMonth = this.month - 1;
                    newDay = 31;
                }
            }
            else if(day==1 && (this.month==5 || this.month==7 || this.month==10 || this.month==12)){
                newYear = this.year;
                newMonth = this.month - 1;
                newDay = 30;
            }
            else if(day==1 && month==3 && !isLeapYear(year)){
                newYear = this.year;
                newMonth = 2;
                newDay = 28;
            }
            else if(day==1 && month==3 && isLeapYear(year)){
                newYear = this.year;
                newMonth = 2;
                newDay = 29;
            }
            else{
                newYear = this.year;
                newMonth = this.month;
                newDay = this.day - 1;
            }
            return new DateUtil(newYear, newMonth, newDay);
        }
        public DateUtil getPreviousNDays(int n) {//取得year-month-day的前n天日期
            DateUtil newDate = new DateUtil(year,month,day);
            for (int i=0;i<n;i++){
                newDate = newDate.getPreviousDay();
            }
            return newDate;
        }
        public boolean compareDates(DateUtil date) {//比较当前日期与date的大小(先后)
            if (this.year > date.getYear()) {
                return true;
            }
            else if (this.year < date.getYear()) {
                return false;
            }
            else {
                if (this.month > date.getMonth()) {
                    return true;
                }
                else if (this.month < date.getMonth()) {
                    return false;
                }
                else {
                    if (this.day > date.getDay()) {
                        return true;
                    }
                    else {
                        return false;
                    }
                }
            }
        }
        public boolean equalTwoDates(DateUtil date) {//判断两个日期是否相等
            if (this.year == date.getYear() && this.month == date.getMonth() && this.day == date.getDay()) {
                return true;
            }
            else
                return false;
        }
        public int getDaysofDates(DateUtil date) {//求当前日期与date之间相差的天数
            int days = 0;
            if (compareDates(date)) {
                while (!equalTwoDates(date)) {
                    date = date.getNextDay();
                    days++;
                }
            }
            else {
                while (!equalTwoDates(date)) {
                    date = date.getPreviousDay();
                    days++;
                }
            }
            return days;
        }
        public String showDate(){//以“year-month-day”格式返回日期值
            return year+"-"+month+"-"+day;
        }
    }

题目4是题目3的拓展,如果整理好思路和设计对方法可以较快解决这道题。参考题目3(求下一天),设计一个求下一天的方法,在求下n天的方法中的循环中调用,求前n天是同一个道理,设计一个求前一天的方法,在求前n天的方法中的循环中调用。而在求当前日期与date之间相差的天数,也调用了求下一天的方法和求前一天的方法,以及比较当前日期与date的大小(先后)的方法和判断两个日期是否相等的方法,如在先,则循环求下一天直至两个日期相等;如在后,则循环求前一天直至两个日期相等。不过我这个代码写的很糟糕,具体在踩坑心得中说吧。

三、踩坑心得

踩坑心得主要是对训练集03的第三题和第四题进行总结。

 

  • 题目3提交了差不多5次,编译成功后主要是无效边界值测试总是过不去,一开始跨年测试和闰年12月底测定点也没过,后来发现,其实是格式不对,我却还以为我在闰年的时候把mon_maxnum[2]的值改成29,而后面没改回来的原因,折腾了一番才突然醒悟,在闰年的时候把mon_maxnum[2]的值改成29放在if里面,怎么也不影响后面的过程。还有一个原因可能是其中有一个测试点应该是输入2000 12 31是,我也认定为输入数据非法。

以下是只得了22分的代码和测试点错误截图:

     

 

 

import java.util.Scanner;

public class Main{
    static class Date{
        private int year;
        public int getYear(){
            return this.year;
        }
        public void setYear(int year){
            if(year>=1900&&year<=2000){
                this.year=year;
            }
            else{
                System.out.println("Date Format is Wrong");
                return;
            }
        }
        private int month;
        public int getMonth(){
            return this.month;
        }
        public void setMonth(int month){
            if(month>=1&&month<=12){
                this.month=month;
            }
            else{
                System.out.println("Date Format is Wrong");
                return;
            }
        }
        private int day;
        public int getDay(){
            return this.day;
        }
        public void setDay(int day){
            if(day>=1&&day<=31){
                this.day=day;
            }
            else{
                System.out.println("Date Format is Wrong");
                return;
            }
        }
        public Date(){
            
        }
        public Date(int year,int month,int day){
            this.year=year;
            this.month=month;
            this.day=day;
        }
        private int[] mon_maxnum=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
        public boolean isLeapYear(int year){
            if(year%4==0&&year%100!=0||year%400==0){
                return true;
            }
            else{
                return false;
            }
        }
        public boolean checkInputValidity(){
            if(this.month==2){
                if(this.year%4==0&&this.year%100!=0||this.year%400==0){
                    if(this.day>29)
                        return false;
                    else
                        return true;
                 }
                else{
                    if(this.day>28)
                        return false;
                    else
                        return true;
                }
             }
            if(this.day>mon_maxnum[this.month])
                return false;
            else
                return true;
        }
        public void getNextDate(){
        if(this.year%4==0&&this.year%100!=0||this.year%400==0){
            mon_maxnum[2]=29;
            if(this.month==12&&this.day==31){
                if(this.year==2000)
                    System.out.print("Date Format is Wrong");
                else if(this.year!=2000)
                    System.out.print("Next day is:"+(this.year+1)+"-1-1");
            }
            else if(this.month!=12 && this.day==mon_maxnum[this.month]){
                System.out.print("Next day is:"+this.year+"-"+(this.month+1)+"-1");
            }
            else{
                System.out.print("Next day is:"+this.year+"-"+this.month+"-"+(this.day+1));
            }
        }
        else{
            if(this.month==12&&this.day==31){
                if(this.year==2000)
                    System.out.print("Date Format is Wrong");
                else if(this.year!=2000)
                    System.out.print("Next day is:"+(this.year+1)+"-1-1");
            }
            else if(this.month!=12 && this.day==mon_maxnum[this.month]){
                System.out.print("Next day is:"+this.year+"-"+(this.month+1)+"-1");
            }
            else{
                System.out.print("Next day is:"+this.year+"-"+this.month+"-"+(this.day+1));
            }
        }
        }
    }
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        Date d=new Date();
        int year=in.nextInt();
        int month=in.nextInt();
        int day=in.nextInt();
        d.getYear();
        d.setYear(year);
        d.getMonth();
        d.setMonth(month);
        d.getDay();
        d.setDay(day);
        if(d.checkInputValidity()){
            d.getNextDate();
        }
        else{
            System.out.print("Date Format is Wrong");
        }
    }
}

全是无效边界值测试点错误,随便输入一个非法测试值,运行结果如下:

可以很清楚地看到,输出“Date Format is Wrong"后还紧接着输出了下一天。

再看其它的测试值

可以看到闰年平年的二月测试是没有问题的,问题出在年份和月份上,月份输入非法以及月和日对应不上又会再输出一遍”Date Format is Wrong"。所以问题应该出在年份还有return上。也是我没设计好的原因,我对于非法输入的判断写的很分散,并没有全部写在一个方法里,后来修改在全都写在一个方法checkInputValidity(),就解决了这个问题。

  • 题目4踩的最大一个坑是内存超限。

我真的,哭死。本来以为我想的这个设计天衣无缝(详情见二、设计与分析),没想到居然内存超限了......

在idea上测试这两个点,答案是也是错的.......后面又小改了下方法,结果错的测试点更多,但是内存不超限了,反正越改越错......后来听了同学的建议,我重新写过了getNextDays()方法,代码如下:

        public DateUtil getNextNDays(int n) {//取得year-month-day的下n天日期
            DateUtil newDate = new DateUtil(year, month, day);
            int newYear = this.year;
            int newMonth = this.month;
            int newDay = this.day;
            for (int i = 0; i < n; i++) {
                //newDate = newDate.getNextDay();这是之前写的方法里,调用getNextDay(),这样写会内存超限
            if(newYear%4==0&&newYear%100!=0||newYear%400==0){
                mon_maxnum[2]=29;
                if(newMonth==12&&newDay==31){
                        newYear =newYear + 1;
                        newMonth = 1;
                        newDay = 1;
                }
                else if(newMonth!=12 && newDay==mon_maxnum[newMonth]){
                    newMonth = newMonth + 1;
                    newDay = 1;
                }
                else{
                    newDay = newDay + 1;
                }
            }
            else{
                mon_maxnum[2]=28;
                if(newMonth==12&&newDay==31){
                        newYear = newYear + 1;
                        newMonth = 1;
                        newDay = 1;
                }
                else if(newMonth!=12 && newDay==mon_maxnum[newMonth]){
                    newMonth = newMonth + 1;
                    newDay = 1;
                }
                else{
                    newDay = newDay + 1;
                }
            }
            }
            return new DateUtil(newYear, newMonth, newDay);
        }

我不在getNextDays()里调用getNxetDay(),删除之后重新写过,就好了,求下n天的代码超限的问题解决了,求前n天的问题也是一样的,所以我打算,用和求下n天一样的解决办法,然后写完发现,代码长度又超出限制!.......我的代码太乱太冗长了,再这么一改,已经有三四百行了。但是又不能直接删掉getNxetDay()和getPreviousDay(),因为我在getDaysofDates(DateUtil date)中也调用了这两个方法,如果删掉,getDaysofDates(DateUtil date)也要重新写过,但我暂时还没想到怎么重新写,我当时脑子里就这一个方案。

四、改进建议


对于训练集03的题目四,上面已经说过问题了,如果把getNxtDay()和getPreviousDay()删掉,那么重新写过getDaysofDates(DateUtil date),代码如下:
 1 public int getDaysofDates(DateUtil date){
 2         int count1=0;
 3         int count2=0;
 4         for(int i=1820;i<this.year;i++){
 5             if(isLeapYear(i))
 6                 count1+=366;
 7             else count1+=365;
 8         }
 9         for(int j=1;j<this.month ;j++){
10             if(isLeapYear(this.year)){
11                 mon_maxnum[2]=29;
12             }
13             else mon_maxnum[2]=28;
14             count1+=mon_maxnum[j];
15         }
16         count1+=this.day ;
17         for(int i=1820;i<date.year;i++){
18             if(isLeapYear(i))
19                 count2+=366;
20             else count2+=365;
21         }
22         for(int j=1;j<date.month ;j++){
23             if(isLeapYear(date.year)){
24                 mon_maxnum[2]=29;
25             }
26             else mon_maxnum[2]=28;
27             count2+=mon_maxnum[j];
28         }
29         count2+=date.day ;
30         return Math.abs(count1-count2) ;
31     }

这样改过之后,再把getNxtDay()和getPreviousDay()删掉,getPreviousDays()参照getNxtDays()重新写过,不再调用getPreviousDay(),内存不超限,代码也不会超过规定长度。

另外,对于这三次训练集,我应该再多一些注释,目前看来,这三次训练集的题目我是一点注释没写,之后应该多写注释。因为在后面修改代码时,一旦代码一长,我自己也总找不到自己要找要修改的代码在哪,一定要养成写注释的习惯。

五、总结

       通过这三次训练集,我对Java语法的运用更加熟练了,前两个星期主要学习和练习Java语法。第三个星期主要学习了类的设计,学习了采用内部类实现对象的创建和访问控制,封装成员变量和方法来确保信息安全和正确性。通过训练,能够运用一点点一些比较典型的面向对象编程思想和技巧,但是还不足以在面向对象这一门中达到入门。在写PTA作业时,还是感到很匆忙,感觉时间不够用,还须加强时间管理能力。对一些Java语法的知识点还是不太了解,没有学习完全,有时候还需要查找资料来辅助完成作业,还须在Java语法方面再深入学习。

       不足还有很多,少年还须努力。

posted @ 2023-03-26 00:01  Jally373  阅读(16)  评论(0)    收藏  举报