#面向对象程序设计作业回顾# 第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类结构如下图所示:
输入格式:
在一行内输入年月日的值,均为整型数,可以用一到多个空格或回车分隔。
输出格式:
当输入数据非法及输入日期不存在时,输出“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");

浙公网安备 33010602011771号