#面向对象程序设计作业回顾# 第1、2、3次作业总结(一)

一、前言

前三次作业的题量在整个OOP课程当中属于题量较小的情况,但对于初次接触面向对象的我来说,这些题也花费了不少的时间来完成。难度上来说,这三套题集都有明显的难度梯度划分,从前往后的难度是从易到难,在每个题目集内部难度分布也是如此,符合课程学习的一般规律。三次题目集整体难度不高,主要是为了让我们快速了解和熟悉一些基本的java语法,以及一些常用的类。现对前三次题目集的知识部分进行回顾,将涉及到的知识点尽可能全面地罗列出来。

(一)知识点

  • 代码风格需遵守阿里巴巴Java开发手册的编码规范,例如:
if(A<20&&A>0)
        {
            cost=12+(A-1)*2;
        }
// 不符合标准的格式:运算符之间无空格、if无空格且其后第一个花括号单独占一行、变量名太随意,无法做到 “见名知意”、夸张的缩进

if (weight < 20 && weight > 0){
    cost = 12 + (weight - 1 ) * 2;
   }
// 符合标准的格式
  • Java导入工具包的方式及常见方法所属的工具包,例如:Scanner类需要用 import java.util.Scanner; 导入
  • 对象的概念
  • 类的概念及如何自定义类并实现一些简单功能,例如:
class Circle {// 创建一个圆形类
    private double radius;
public double getRadius() {
        return this.radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    public double getS() {
        return (Math.PI) * this.radius * this.radius;
    }
}
  • List集合下的字符串类StringBuffer的常见方法
  • 泛型的概念

二、设计与分析

题目集3的第三题和第四题的综合性在所有题目中最强,基本涵盖了前两套题目集中的所有知识点,因此这里作者只分析这两题

题目集3,第3题:

1. 原题放送:

7-3定义日期类

作者 段喜龙
单位 南昌航空大学
定义一个类Date,包含三个私有属性年(year)、月(month)、日(day),均为整型数,其中:年份的合法取值范围为[1900,2000] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。
注意:不允许使用Java中和日期相关的类和方法,否则按0分处理。

要求:Date类结构如下图所示:w
输入格式:
在一行内输入年月日的值,均为整型数,可以用一到多个空格或回车分隔。

输出格式:
当输入数据非法及输入日期不存在时,输出“Date Format is Wrong”;
当输入日期合法,输出下一天,格式如下:Next day is:年-月-日

输入样例1:
在这里给出一组输入。例如:

1912 12 25
输出样例1:
在这里给出相应的输出。例如:

Next day is:1912-12-26
输入样例2:
在这里给出一组输入。例如:

2001 2 30
输出样例2:
在这里给出相应的输出。例如:

Date Format is Wrong

代码长度限制
16 KB
时间限制
400 ms
内存限制
64 M

2. 题目分析:

这道题由于给出了我们Date的类图,因此不需要我们自己设计,只需要根据类图将类实现即可,难度不高,重点在于正确识读类图

需要注意的是这个类有两种构造方法,可进行重载,一种构造方法是默认的,另一种构造方法是传入year,month,day进行初始化

3. 代码设计:

我的代码
在实现 getNextDay() 这个方法时,调用了isLeapYear() 方法,根据是否为闰年,把日期的进位情况分类讨论

三、踩坑心得

我的提交的结果:

从测试点不难看出,平台进行了多个无效值测试,其中有一个无效值是我在设计checkInputValidity() 方法时没有考虑到的,通过多次尝试,摸索出了该非法边界值。

测试用例
1900 1 0

输出结果:

Next day is:1900-1-1


显然,1900年1月0日是一个错误的输入。由于该类内部方法采用的是模块化设计,我们很快就能根据各个方法的职责定位到有问题的代码,即checkInputValidity() 方法,以下是作者最初的checkInputValidity() 方法。

 1 public boolean checkInputValidity() {
 2         boolean flag = true;
 3         if (this.year < 1900 || this.year > 2000 || this.month < 1 || this.month > 12) {
 4             flag = false;
 5         } else if (isLeapYear(this.year)) {
 6             if (this.month != 2) {
 7                 if (this.day < 0 || this.day > mon_maxnum[this.month]) {
 8                     flag = false;
 9                 }
10             } else {
11                 if (this.day > 29 || this.day < 1) {
12                     flag = false;
13                 }
14             }
15         } else {
16             if (this.day < 0 || this.day > mon_maxnum[this.month]) {
17                 flag = false;
18             }
19         }
20         if(flag == false){
21             System.out.print("Date Format is Wrong\n");
22         }
23         return flag;
24  }

根据上面的测试用例,推断是第7行和第16行 if (this.day < 0 || this.day > mon_maxnum[this.month]) 出现问题,我们仔细看一下这个逻辑,一个满足 0 <= this.day <= mon_maxnum[this.month]的 day 的值被认为是合法的,则day = 0也合法。这不符合日期的逻辑,因此只需要修改为 if (this.day < 1 || this.day > mon_maxnum[this.month]) 即可

四、改进建议

(一)遵循SRP原则

以下面checkInputValidity() 方法为例:

 1    public boolean checkInputValidity() {
 2         boolean flag = true;
 3         if (this.year < 1900 || this.year > 2000 || this.month < 1 || this.month > 12) {
 4             flag = false;
 5         } else if (isLeapYear(this.year)) {
 6             if (this.month != 2) {
 7                 if (this.day < 0 || this.day > mon_maxnum[this.month]) {
 8                     flag = false;
 9                 }
10             } else {
11                 if (this.day > 29 || this.day < 1) {
12                     flag = false;
13                 }
14             }
15         } else {
16             if (this.day < 1 || this.day > mon_maxnum[this.month]) {
17                 flag = false;
18             }
19         }
20         if(flag == false){
21             System.out.print("Date Format is Wrong\n");
22         }
23         return flag;
24     }

第20~22行的输出放在这个方法里不太符合单一职责原则,“输出”的职责不应该放在 “判断输入是否合法” 的方法中

符合SRP原则的编码方式应该是在主函数中根据checkInputValidity() 的返回值决定是否执行Java System.out.print("Date Format is Wrong\n");

进入下一篇《#面向对象程序设计作业回顾# 前三次作业(二)》→

posted @ 2023-03-22 16:21  一杯大丞汁  阅读(109)  评论(4)    收藏  举报