Java第四~六次作业总结


R第二次博客作业——Java第四~六次作业总结

一、前言:

1.知识点:

(1)第四次题目集:正则表达式的应用、日期问题中面向对象程序设计以及Java集合框架的搭建、类的继承关系;

(2)第五次题目集:日期问题中面向对象程序设计(聚合二,相同的需求,第二种类的设计方案)、正则表达式的应用、有序数组的合并、整型数据排序(插入\选择\冒泡排序);

(3)第六次题目集:正则表达式的应用、继承与多态、接口及多态性。

2.题量和难度:

    这三次作业相对于前面三次PTA作业,题量和难度都有比较大的提高。第四次和第五次题目集虽然题目量都不算大,分别只有三道和四道,但真正上手做起来确实没有那么容易。第六次题目集一共有六道题,由于题型相对前两次讲相对基础,所以做起来也顺利很多。

    第四次题目集三道题分别是水文数据校验和处理、日期问题面向对象设计(聚合一)以及图形继承。其中尤其第二题花费了比较多的时间去理解、搭建类的关系体系结构,结构搭建起来后,其中一些具体的算法实现起来就顺利了很多,只是要注意一些细节处的要求。另外两道题,由于正则表达式和类的继承关系当时也是刚刚学,难度主要体现在不熟悉上,自己则是在网上找了一些相似的例子,模仿着例子来实现题目的要求,整体难度来讲偏难,但还可以接受。

    第五次题目集四道题分别是日期问题面向对象设计(聚合二)、统计Java程序中关键词的出现次数、合并两个有序数组为新的有序数组、对整型数据排序。后面两道题涉及的知识点是之前学习数据结构重点学习过的,像有序数组的合并、三种经典的排序方法(选择、插入、冒泡),做起来也比较顺利。第一题(聚合二)则更像是之前(聚合一)基础上的一种改进,另外一种类的关系体系结构搭建方法。我认为最难到我的要数第二题,统计Java程序中关键词的出现次数,自己看了很多的例子才勉强理解,动手实现起来也磕磕绊绊的,着实花了不少时间。

    第六次题目集六道题,前四道是正则表达式一些基础性的训练,一共加起来也没多少行代码,写起来也挺快的。后两道题则是类的继承关系相关的应用,第五题图形的继承与多态、第六题实现图形接口及多态性,相对来讲第五题实现起来的难度比第六题稍大一些,主要也是体现在一些比较陌生的Java类的使用上,这次用上了下次就记得在Java里还有这种方法。整体来讲难度还行。

二、设计与分析:

1.两种日期类聚合设计的优劣比较

  • 题目集4(7-2) 日期问题面向对象设计(聚合一):参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] 。

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

    1. 求下n天
    2. 求前n天
    3. 求两个日期相差的天数
(1)源代码:
  1 package pta;
  2 
  3 import java.util.Scanner;
  4 
  5 public class Main {
  6 
  7     public static void main(String[] args) {
  8         // TODO Auto-generated method stub
  9         Scanner in=new Scanner(System.in);
 10         int bh=in.nextInt();        //编号
 11         int year=in.nextInt(); int month=in.nextInt(); int day=in.nextInt();
 12         DateUtil date1=new DateUtil(year,month,day);
 13         
 14         switch(bh) {
 15             //测试输入日期的下n天
 16             case 1:{
 17                 int n=in.nextInt();        //n天
 18                 if(!date1.checkInputValidity()||n<0) {
 19                     System.out.print("Wrong Format");
 20                     System.exit(0);
 21                 }
 22                 else
 23                     System.out.print(date1.getNextNDays(n).showDate());
 24             }
 25             break;
 26             //测试输入日期的前n天
 27             case 2:{
 28                 int n=in.nextInt();        //n天
 29                 if(!date1.checkInputValidity()||n<0) {
 30                     System.out.print("Wrong Format");
 31                     System.exit(0);
 32                 }
 33                 else
 34                     System.out.print(date1.getPreviousNDays(n).showDate());
 35             }
 36             break;
 37             //测试两个日期之间相差的天数
 38             case 3:{
 39                 //输入第二个年月日
 40                 int year2=in.nextInt(); int month2=in.nextInt(); int day2=in.nextInt();
 41                 DateUtil date2=new DateUtil(year2,month2,day2);
 42                 if(!date1.checkInputValidity()||!date2.checkInputValidity()) {
 43                     System.out.print("Wrong Format");
 44                     System.exit(0);
 45                 }
 46                 else
 47                     System.out.print(date1.getDaysofDates(date2));
 48             }
 49             break;
 50             default :
 51                 System.out.print("Wrong Format");
 52         }
 53         in.close();
 54     }
 55 }
 56 //DateUtil日期处理类
 57 class  DateUtil{
 58     Day day;
 59     
 60     //默认构造方法
 61     DateUtil(){
 62         
 63     }
 64     //带参构造方法
 65     DateUtil(int y, int m, int d) {
 66         this.day=new Day(y,m,d);
 67     }
 68     //day getter
 69     Day getDay(){
 70         return day;
 71     }
 72     //day setter
 73     void setDay(Day d) {
 74         this.day = d;
 75     }
 76     //校验数据合法性
 77     boolean checkInputValidity() {
 78         if(this.day.validate()&&this.day.getMonth().validate()&&this.day.getMonth().getYear().validate())
 79             return true;
 80         else    return false;
 81     }
 82     //比较两个日期的大小
 83     boolean compareDates(DateUtil date) {
 84         int y1 = this.day.getMonth().getYear().getValue();
 85         int y2 = date.day.getMonth().getYear().getValue();
 86         int m1 = this.day.getMonth().getValue();
 87         int m2 = date.day.getMonth().getValue();
 88         //年小或月小或日小
 89         if(y1this.day.getValue())
 90             return true;
 91         else    return false;
 92     }
 93     //判定两个日期是否相等
 94     boolean equalTwoDates(DateUtil date) {
 95         int y1 = this.day.getMonth().getYear().getValue();
 96         int y2 = date.day.getMonth().getYear().getValue();
 97         int m1 = this.day.getMonth().getValue();
 98         int m2 = date.day.getMonth().getValue();
 99         if(y1==y2&&m1==m2&&date.day.getValue()==this.day.getValue())
100             return true;
101         else    return false;
102     }
103     //日期值格式化
104     String showDate() {
105         int y=this.day.getMonth().getYear().getValue();
106         int m=this.day.getMonth().getValue();
107         int d=this.day.getValue();
108         return y+"-"+m+"-"+d;
109     }
110     //求下n天
111     DateUtil getNextNDays(int n) {
112          int i=0;
113           while (i<n)
114           {
115               this.getDay().dayIncrement();
116               i++;
117           }
118             return new DateUtil(this.getDay().getMonth().getYear().getValue(),this.getDay().getMonth().getValue(),this.getDay().getValue());
119     }
120     //求前n天
121     DateUtil getPreviousNDays(int n) {
122          int i=0;
123             while (i<n)
124             {
125                 this.getDay().dayReduction();
126                 i++;
127             }
128             return new DateUtil(this.getDay().getMonth().getYear().getValue(),this.getDay().getMonth().getValue(),this.getDay().getValue());
129     }
130     //求两个日期之间的天数
131     int getDaysofDates(DateUtil date) {
132            int i=0;
133               if(equalTwoDates(date))
134                   return 0;
135               else if(compareDates(date))
136               {
137                   while(!equalTwoDates(date))
138                   {
139                       getDay().dayIncrement();
140                       i++;
141                   }
142               }
143               else {
144                   while(!equalTwoDates(date))
145                   {
146                       getDay().dayReduction();
147                       i++;
148                   }
149               }
150               return i;
151     }
152 }
153 //Day日期类
154 class Day{
155     int value;
156     Month month;
157     int[] mon_maxnum={31,28,31,30,31,30,31,31,30,31,30,31};
158     
159     //默认构造方法
160     Day(){
161         
162     }
163     //带参构造方法
164     Day(int yearValue,int monthValue,int dayValue){
165         this.month=new Month(yearValue,monthValue);
166         this.value=dayValue;
167     }
168     //value getter
169     int getValue(){
170         return value;
171     }
172     //value setter
173     void setValue(int value){
174         this.value=value;
175     }
176     //month getter
177     Month getMonth(){
178         return month;
179     }
180     //month setter
181     void setMonth(Month value){
182         this.month=value;
183     }
184     //日期复位(1)
185     void resetMin() {
186         value=1;
187     }
188     //日期设为该月最大值
189     void resetMax() {
190         int y=month.getYear().getValue();
191         if(month.getYear().isLeapYear(y))    mon_maxnum[2-1]=29;
192         value=mon_maxnum[month.getValue()-1];
193     }
194     //校验数据合法性
195     boolean validate() {
196         int y=month.getYear().getValue();
197         int m=month.getValue();
198         if(month.getYear().isLeapYear(y))    mon_maxnum[2-1]=29;
199         if(value>=1&&value<=mon_maxnum[m-1])    return true;
200         else    return false;
201     }
202     //日期增1
203     void dayIncrement() {
204         value++;
205     }
206     //日期减1
207     void dayReduction() {
208         value--;
209     }
210 }
211 //Month月份类
212 class Month{
213     int value;
214     Year year;
215     
216     //默认构造方法
217     Month(){
218         
219     }
220     //带参构造方法
221     Month(int yearValue,int monthValue) {
222         this.year=new Year(yearValue);
223         this.value=monthValue;
224     }
225     //value getter
226     int getValue() {
227         return value;
228     }
229     //value setter
230     void setValue(int value) {
231         this.value=value;
232     }
233     //year getter
234     Year getYear() {
235         return year;
236     }
237     //year setter
238     void setYear(Year year) {
239         this.year=year;
240     }
241     //月份复位(1)
242     void resetMin() {
243         value=1;
244     }
245     //月份设置为12
246     void resetMax() {
247         value=12;
248     }
249     //校验数据合法性
250     boolean validate() {
251         if(value>=1&&value<=12)        return true;
252         else    return false;
253     }    
254     //月份增1
255     void monthIncrement() {
256         value++;
257     }
258     //月份减1
259     void monthReduction() {
260         value--;
261     }
262 }
263 //Year年份类
264 class Year{
265     int value;
266     
267     //默认构造方法
268     Year(){
269         
270     }
271     //带参构造方法
272     Year(int value) {
273         this.value=value;
274     }
275     //value getter
276     int getValue() {
277         return value;
278     }
279     //value setter
280     void setValue(int value) {
281         this.value = value;
282     }
283     //判断是否为闰年
284     boolean isLeapYear(int year) {
285         if(year%4==0&&year%100!=0||year%400==0)
286             return true;
287         else    return false;
288     }
289     //校验数据合法性
290     boolean validate() {
291         if(value>=1900&&value<=2050)    return true;
292         else    return false;
293     }
294     //年份增1
295     void yearIncrement() {
296         value++;
297     }
298     //年份减1
299     void yearReduction() {
300         value--;
301     }
302 }
(2)SourceMonitor的生成报表内容

 

(3)PowerDesigner的相应类图

(4)解释和心得:

 这道题通过题目给出的类图可以很清晰得观察整个程序设计类相互关系的体系框架:

main类中包含main函数,主要用途是接收输入的数据,并通过调用类DateUtil中一些具体的方法实现题目的具体要求(像求当前日期后\前N天的日期、求两个日期之间的天数),可以通过输入选项编号1~3来选择程序计算进入以上三种的哪一种。除此之外,通过调用类DateUtil中的checkInputValidity方法以及自检输入选项编号的检测,实现对输入数据合法性的检测判断,若输入有误则打印Wrong Format;

DateUtil类中包含一个实体类Day day、两种自身的构造方法(默认构造方法和带参构造方法)以及一系列具体的日期相关处理方法(像前面提到的校验数据合法性checkInputValidity()、比较两个日期大小compareDates()、判定两个日期是否相等equalTwoDates()以及求当前日期后\前N天的日期、求两个日期之间的天数等等),同时它还可以对实体类Day进行一些操作,比如返回day的值或者设置day的值。总体来讲日期处理类是整个程序设计的核心部分,各种所需的操作方法大都聚合于此。

剩下部分则是三个日期类:Day类、Month类、Year类。它们分别包含了一些自己私有的属性和方法,像自己的参数值,返回自身的值或者设置自身的值,检测自身参数值的合法性,加一减一以及设为最大值或最小值等等。值得一提的是,在这次日期问题面向对象设计方案中,Day类中包含有一个month实体类,Month类中包含有一个year实体类,即在DateUtil类中,可通过调用类Day再调用类Month最后调用类Year,实现对Year类中的属性和方法的访问和调用。

  • 题目集5(7-5) 日期问题面向对象设计(聚合二):参考题目7-3的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] 。

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

    1. 求下n天
    2. 求前n天
    3. 求两个日期相差的天数
(1)源代码:
  1 package pta;
  2 
  3 import java.util.*;
  4 
  5 public class Main {
  6     public static void main(String[] args) {
  7         // TODO Auto-generated method stub
  8         Scanner in = new Scanner(System.in);
  9         int xx = in.nextInt();        //编号
 10         int year = in.nextInt();    int month = in.nextInt();    int day = in.nextInt();
 11         DateUtil dateutil=new DateUtil(year,month,day);
 12         
 13         switch(xx) {
 14             //测试输入日期的下n天
 15             case 1:{
 16                 int n = in.nextInt();        //n天
 17                 if(!dateutil.checkInputValidity()) {
 18                     System.out.println("Wrong Format");
 19                 }
 20                 else
 21                     System.out.println(year+"-"+month+"-"+day+" next "+n+" day is:"+dateutil.getNextNDays(n).showDate());
 22             }break;
 23             //测试输入日期的前n天
 24             case 2:{
 25                 int n = in.nextInt();        //n天
 26                 if(!dateutil.checkInputValidity()) {
 27                     System.out.println("Wrong Format");
 28                 }
 29                 else
 30                     System.out.println(year+"-"+month+"-"+day+" previous "+n+" day is:"+dateutil.getPreviousNDays(n).showDate());
 31             }break;
 32             //测试两个日期之间相差的天数
 33             case 3:{
 34                 //输入第二个年月日
 35                 int year1 = in.nextInt();    int month1 = in.nextInt();    int day1 = in.nextInt();
 36                 DateUtil du1=new DateUtil(year1,month1,day1);
 37                 if(!dateutil.checkInputValidity()||!du1.checkInputValidity()) {
 38                     System.out.println("Wrong Format");
 39                 }
 40                 else
 41                     System.out.println("The days between "+year+"-"+month+"-"+day+" and "+year1+"-"+month1+"-"+day1+" are:"+dateutil.getDaysofDates(du1));
 42             }break;
 43             default :
 44                 System.out.println("Wrong Format");
 45         }
 46     }
 47 }
 48 //Year年份类
 49 class Year{
 50     int value;
 51     
 52     //默认构造方法
 53     Year(){
 54         
 55     }
 56     //带参构造方法
 57     Year(int Value) {
 58         this.value=Value;
 59     }
 60     //value getter
 61     int getValue() {
 62         return value;
 63     }
 64     //value setter
 65     void setValue(int value) {
 66         this.value = value;
 67     }
 68     //判断是否为闰年
 69     boolean isLeapYear() {
 70         if(value%4==0&&value%100!=0||value%400==0)    return true;
 71         else    return false;
 72     }
 73     //校验数据合法性
 74     boolean validate() {
 75         if(value>=1820&&value<=2020)    return true;
 76         else    return false;
 77     }
 78     //年份增1
 79     void yearIncrement() {
 80         value++;
 81     }
 82     //年份减1
 83     void yearReduction() {
 84         value--;
 85     }
 86 }
 87 //Month月份类
 88 class Month{
 89     int value;
 90     
 91     //默认构造方法
 92     Month(){
 93         
 94     }
 95     //带参构造方法
 96     Month(int Value) {
 97         this.value=Value;
 98     }
 99     //value getter
100     int getValue() {
101         return value;
102     }
103     //value setter
104     void setValue(int value) {
105         this.value = value;
106     }
107     //月份复位(1)
108     void resetMin() {
109         value = 1;
110     }
111     //月份设置为12
112     void resetMax() {
113         value = 12;
114     }
115     //校验数据合法性
116     boolean validate() {
117         if(value>=1&&value<=12)        return true;
118         else    return false;
119     }    
120     //月份增1
121     void monthIncrement() {
122         value++;
123     }
124     //月份减1
125     void monthReduction() {
126         value--;
127     }
128 }
129 //Day日期类
130 class Day{
131     int value;
132     
133     //默认构造方法
134     Day(){
135         
136     }
137     //带参构造方法
138     Day(int Value){
139         this.value=Value;
140     }
141     //value getter
142     int getValue(){
143         return value;
144     }
145     //value setter
146     void setValue(int value){
147         this.value = value;
148     }
149     //日期增1
150     void dayIncrement() {
151         value++;
152     }
153     //日期减1
154     void dayReduction() {
155         value--;
156     }
157 }
158 //DateUtil日期处理类
159 class  DateUtil{
160     Year year;
161     Month month;
162     Day day;
163     int[] mon_maxnum = {31,28,31,30,31,30,31,31,30,31,30,31};
164     
165     //默认构造方法
166     DateUtil(){
167         
168     }
169     //带参构造方法
170     DateUtil(int y,int m,int d) {
171         this.year=new Year(y);        this.month=new Month(m);    this.day=new Day(d);
172     }
173     //year getter
174     Year getYear(){
175         return year;
176     }
177     //year setter
178     void setYear(Year year) {
179         this.year = year;
180     }
181     //month getter
182     Month getMonth(){
183         return month;
184     }
185     //month setter
186     void setMonth(Month month) {
187         this.month = month;
188     }
189     //day getter
190     Day getDay(){
191         return day;
192     }
193     //day setter
194     void setDay(Day d) {
195         this.day = d;
196     }
197     //日期复位(1)
198     void setDayMin() {
199         this.day.value = 1;
200     }
201     //日期设为该月最大值
202     void setDayMax() {
203         if(this.year.isLeapYear())        mon_maxnum[2]=29;
204         this.day.value = mon_maxnum[this.month.value];
205     }
206     //校验数据合法性
207     boolean checkInputValidity() {
208         if(this.year.isLeapYear())        mon_maxnum[2] = 29;
209         if(!year.validate() || !month.validate() ||this.day.value>=1&&this.day.value<=mon_maxnum[this.month.value])    return true;
210         else    return false;
211     }
212     //求下n天
213     DateUtil getNextNDays(int n) {
214         int y = this.getYear().getValue();    int m = this.getMonth().getValue();    int d = this.getDay().getValue();
215         int[] a = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31};
216         
217         if(this.year.isLeapYear())    a[2] = 29;
218         int jday=d;
219         d+=n;
220         //不在当月
221         while(d>a[m]) {
222             month.monthIncrement();
223             if(m==13) {    //不在当年
224                 month.resetMin();    year.yearIncrement();
225             }
226             d=n-(a[m]-jday);
227         }
228         return new DateUtil(y,m,d);
229     }
230     //求前n天
231     DateUtil getPreviousNDays(int n) {
232         int y = this.getYear().getValue();    int m = this.getMonth().getValue();    int d = this.getDay().getValue();
233         int[] a = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31};
234         
235         if(this.year.isLeapYear())    a[2] = 29;
236         int jday=d;
237         d+=n;
238         //不在当月
239         while(d>a[m]) {
240             month.monthIncrement();
241             if(m==13) {    //不在当年
242                 month.resetMin();    year.yearIncrement();
243             }
244             d=n-(a[m]-jday);
245         }
246         return new DateUtil(y,m,d);
247     }
248     //比较两个日期的大小
249     boolean compareDates(DateUtil date) {
250         //y1
251         if((date.year.getValue()<this.year.getValue()||date.year.getValue()==this.year.getValue()&&date.month.getValue()<this.month.getValue()||date.year.getValue()==this.year.getValue()&&date.month.getValue()==this.month.getValue()&&this.day.getValue()return true;
252         else    return false;
253     }
254     //判定两个日期是否相等
255     boolean equalTwoDates(DateUtil date) {
256         //y1==y2&&m1==m2&&d1==d2
257         if(date.year.getValue()==this.year.getValue()&&date.month.getValue()==this.month.getValue()&&date.day.getValue()==this.day.getValue())    return true;
258         else    return false;
259     }
260     //求两个日期之间的天数
261     int getDaysofDates(DateUtil date) {
262         int ts = 0;
263         DateUtil b1 = date;
264         DateUtil b2 = this;
265         int year1 = b1.getYear().getValue();    int year2 = b2.getYear().getValue();
266         int month1 = b1.getMonth().getValue();    int month2 = b2.getMonth().getValue();
267         int day1 = b1.getDay().getValue();        int day2 = b2.getDay().getValue();
268         int[] a = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31};
269         
270         //如果date1小于date2
271         if(this.compareDates(date)) {
272             //年同
273             if(year1==year2) {
274                 //闰年
275                 if(this.year.isLeapYear())    a[1] = 29;
276                 //月同
277                 if(month1==month2) {
278                     //日同
279                     if(day1==day2)        ts = 0;
280                     //日不同
281                     else if(day1!=day2)        ts = day2-day1;
282                 }
283                 //月不同
284                 else if(month1!=month2) {
285                     //中间月份天数相加
286                     for(int i=month1+1;ia[i];
287                     //补上两头月份零散的天数
288                     ts+=day2+a[month1]-day1;
289                 }
290             }
291             //年不同
292             else if(year1!=year2) {
293                 //中间年份天数相加
294                 for(int j=year1+1;j) {
295                     ts+=365;
296                     if(j%4==0&&j%100!=0||j%400==0)
297                         ts++;
298                 }
299                 //补上两头年份零散的月份天数
300                 for(int i=month1+1;i<=12;i++)    ts+=a[i];
301                 for(int i=1;ia[i];
302                 //补上两头月份零散的天数
303                 ts+=day2+a[month1]-day1;
304             }
305         }
306         return ts;
307     }
308     //日期值格式化
309     String showDate() {
310         //year-month-day
311         return this.year.value + "-" + this.month.value + "-" + this.day.value;
312     }
313 }
(2)SourceMonitor的生成报表内容

 

(3)PowerDesigner的相应类图

 

(4)解释和心得:

同样, 这道题通过题目给出的类图可以很清晰得观察整个程序设计类相互关系的体系框架,对比(聚合一)类图,我们还是可以发现一些变化的。其中最明显的变化还是在于日期处理DateUtil类以及日期三个类(年月日)之间的关系。

相比于(聚合一)日期处理类DateUtil中仅有一个实体类day,而访问类Month或类Year中的属性和方法则需要通过使用day来间接调用访问(尤其是当需要访问类Year时,需要分别通过类Day和类Month两层),(聚合二)中则实现了日期处理方法的进一步聚合。在这次的类DateUtil中一共包含三个实体类:Year year、Month month、Day day,除了两种DateUtil构造方法以及其他具体的日期处理方法,DateUtil种还包含year、month、day相关的处理操作(返回它们的值或者设置它们的值,将其设为最大值或最小值)。在这种类关系体系框架中,类DateUtil可以实现更方便快捷地访问日期类(年月日),这一点在我们编写日期处理具体方法时感受尤为明显。

综上,我认为(聚合二)类的体系框架设计方案在实际应用中更具优势。

2.三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)

  • 题目集4(7-3) 图形继承:

    编写程序,实现图形类的继承,并定义相应类对象并进行测试。

    1. 类Shape,无属性,有一个返回0.0的求图形面积的公有方法public double getArea();//求图形面积
    2. 类Circle,继承自Shape,有一个私有实型的属性radius(半径),重写父类继承来的求面积方法,求圆的面积
    3. 类Rectangle,继承自Shape,有两个私有实型属性width和length,重写父类继承来的求面积方法,求矩形的面积
    4. 类Ball,继承自Circle,其属性从父类继承,重写父类求面积方法,求球表面积,此外,定义一求球体积的方法public double getVolume();//求球体积
    5. 类Box,继承自Rectangle,除从父类继承的属性外,再定义一个属性height,重写父类继承来的求面积方法,求立方体表面积,此外,定义一求立方体体积的方法public double getVolume();//求立方体体积
    6. 注意:
    • 每个类均有构造方法,且构造方法内必须输出如下内容:Constructing 类名
    • 每个类属性均为私有,且必须有getter和setter方法(可用Eclipse自动生成)
    • 输出的数值均保留两位小数

    主方法内,主要实现四个功能(1-4): 从键盘输入1,则定义圆类,从键盘输入圆的半径后,主要输出圆的面积; 从键盘输入2,则定义矩形类,从键盘输入矩形的宽和长后,主要输出矩形的面积; 从键盘输入3,则定义球类,从键盘输入球的半径后,主要输出球的表面积和体积; 从键盘输入4,则定义立方体类,从键盘输入立方体的宽、长和高度后,主要输出立方体的表面积和体积;

    假如数据输入非法(包括圆、矩形、球及立方体对象的属性不大于0和输入选择值非1-4),系统输出Wrong Format

(1)源代码:
  1 import java.util.Scanner;
  2 
  3 public class Main {
  4     public static void main(String[] args) {
  5         // TODO Auto-generated method stub
  6         int inType;
  7         Scanner in=new Scanner(System.in);
  8         inType=in.nextInt();
  9         
 10         switch(inType){
 11         //定义圆类,从键盘输入圆的半径后,主要输出圆的面积
 12         case 1:
 13             double r=in.nextDouble();
 14             if(r<0.0) {
 15                 System.out.println("Wrong Format");
 16             }
 17             else {
 18                 Circle circle=new Circle();
 19                 circle.setRadius(r);
 20                 System.out.println(String.format("Circle's area:%.2f",circle.getArea()));
 21             }
 22             break;
 23         //定义矩形类,从键盘输入矩形的宽和长后,主要输出矩形的面积
 24         case 2:
 25             double width=in.nextDouble();
 26             double length=in.nextDouble();
 27             if(width<0.0||length<0.0) {
 28                 System.out.println("Wrong Format");
 29             }
 30             else {
 31                 Rectangle rectangle=new Rectangle();
 32                 rectangle.setLength(length);
 33                 rectangle.setWidth(width);
 34                 System.out.println(String.format("Rectangle's area:%.2f",rectangle.getArea()));
 35             }
 36             break;
 37         //定义球类,从键盘输入球的半径后,主要输出球的表面积和体积
 38         case 3:
 39             double r2=in.nextDouble();
 40             if(r2<0.0) {
 41                 System.out.println("Wrong Format");
 42             }
 43             else {
 44                 Ball ball=new Ball();
 45                 ball.setRadius(r2);
 46                 System.out.println(String.format("Ball's surface area:%.2f",ball.getArea()));
 47                 System.out.println(String.format("Ball's volume:%.2f",ball.getVolume()));
 48             }
 49             break;
 50         //定义立方体类,从键盘输入立方体的宽、长和高度后,主要输出立方体的表面积和体积
 51         case 4:
 52             double width2=in.nextDouble();
 53             double length2=in.nextDouble();
 54             double height=in.nextDouble();
 55             if(width2<0.0||length2<0.0||height<0.0) {
 56                 System.out.println("Wrong Format");
 57             }
 58             else {
 59                 Box box=new Box();
 60                 box.setHeight(height);
 61                 box.setWidth(width2);
 62                 box.setLength(length2);
 63                 System.out.println(String.format("Box's surface area:%.2f",box.getArea()));
 64                 System.out.println(String.format("Box's volume:%.2f",box.getVolume()));
 65             }
 66             break;
 67         default:
 68             System.out.println("Wrong Format");
 69         }
 70         
 71         in.close();
 72     }
 73 }
 74 
 75 //类Shape,无属性,有一个返回0.0的求图形面积的公有方法
 76 class Shape 
 77 {
 78 
 79     public Shape() 
 80     {
 81        System.out.println("Constructing Shape");
 82     }
 83     //求图形面积
 84     public double getArea()
 85     {
 86        return 0.0;
 87     }
 88 }
 89 
 90 //类Circle,继承自Shape,有一个私有实型的属性radius(半径),重写父类继承来的求面积方法,求圆的面积
 91 class Circle extends Shape
 92 {
 93 
 94     private double radius;//新定义一个私有属性:半径
 95     
 96     //构造方法,内输出内容
 97     public Circle() 
 98     {
 99        System.out.println("Constructing Circle");
100     }
101     //getter
102     public double getRadius() {// 获取半径
103         return radius;
104     }
105     //setter
106     public void setRadius(double radius) {// 设置半径
107         this.radius = radius;
108     }
109     //重写父类的方法,求圆形面积
110     public double getArea() {
111         return Math.PI*radius*radius;
112     }
113     
114 }
115 //类Rectangle,继承自Shape,有两个私有实型属性width和length,重写父类继承来的求面积方法,求矩形的面积
116 class Rectangle extends Shape
117 {
118     //私有实型属性
119     private double width;
120     private double length;
121     
122     //构造方法
123     public Rectangle() 
124     {
125        System.out.println("Constructing Rectangle");
126     }
127     //getter
128     public double getWidth() {
129         return width;
130     }
131     //setter
132     public void setWidth(double width) {
133         this.width = width;
134     }
135     //getter
136     public double getLength() {
137         return length;
138     }
139     //setter
140     public void setLength(double length) {
141         this.length = length;
142     }
143     //重写父类的方法,求矩形面积
144     public double getArea() {
145         return length*width;
146     }
147     
148 }
149 //类Ball,继承自Circle,其属性从父类继承,重写父类求面积方法,求球表面积
150 //此外,定义一求球体积的方法
151 class Ball extends Circle
152 {
153     //构造方法
154     public Ball() 
155     {
156        System.out.println("Constructing Ball");
157     }
158     //重写父类求面积方法,求球表面积
159     public double getArea() {
160         return 4.0*super.getArea();
161     }
162     //求球体积
163     public double getVolume()
164     {
165         double r2=getRadius();
166         return 4.0/3.0*Math.PI*r2*r2*r2;
167     }
168     
169 }
170 //类Box,继承自Rectangle,除从父类继承的属性外,再定义一个属性height,重写父类继承来的求面积方法,求立方体表面积
171 //此外,定义一求立方体体积的方法
172 class Box extends Rectangle
173 {
174     //私有属性
175     private double height;
176     
177     //构造方法
178     public Box() 
179     {
180        System.out.println("Constructing Box");
181     }
182     //getter
183     public double getHeight() {
184         return height;
185     }
186     //setter
187     public void setHeight(double height) {
188         this.height = height;
189     }
190     //重写父类继承来的求面积方法,求立方体表面积
191     public double getArea() {
192         double l2=getLength();
193         double w2=getWidth();
194         return 2*(super.getArea()+l2*height+w2*height);
195     }
196     //求立方体体积
197     public double getVolume()
198     {
199         double l3=getLength();
200         double w3=getWidth();
201         return l3*w3*height;
202     }
203     
204     
205 }
(2)SourceMonitor的生成报表内容

 

(3)PowerDesigner的相应类图

 

(4)解释和心得:

 通过上方的类图,观察各个类之间的关系:

main类中包含main主方法,主要用途是接收输入,并通过一个switch选择语句选择不同的图形类型并根据题目要求输出相应的结果。

父类Shape(图形类),它是最早的一个图形类,没有包含任何属性,仅有一个返回0.0的求图形面积的公有方法getArea()。构造方法中输出题目要求的内容。

类Circle(圆形类)继承于图形类Shape,其中新定义了一个私有属性radius(半径),可对其进行返回或设置操作。重写了从父类继承的方法getArea(),将返回值修改为计算出的圆的面积。

类Ball(球类)继承于圆形类Circle,继承了父类中的属性和方法,但重写了方法getArea(),将返回值修改为计算出的球的表面积。另外,新定义了一个求球体积的方法getVolume(),其返回值为计算出的球的体积。

类Rectangle(矩形类)继承于图形类Shape,其中新定义了两个私有属性width(宽)和length(长),可对其进行返回或设置操作。重写了从父类继承的方法getArea(),将返回值修改为计算出的矩形的面积。

类Box(立方体类)继承于圆形类Circle,继承了父类中的属性和方法,但重写了方法getArea(),将返回值修改为计算出的立方体的表面积。另外,新定义了一个求立方体体积的方法getVolume(),其返回值为计算出的立方体的体积。

  • 题目集6(7-5) 图形继承与多态:掌握类的继承、多态性及其使用方法。具体需求参见作业指导书。

输入格式:

从键盘首先输入三个整型值(例如a b c),分别代表想要创建的Circle、Rectangle及Triangle对象的数量,然后根据图形数量继续输入各对象的属性值(均为实型数),数与数之间可以用一个或多个空格或回车分隔。

输出格式:

  1. 如果图形数量非法(小于0)或图形属性值非法(数值小于0以及三角形三边关系),则输出Wrong Format
  2. 如果输入合法,则正常输出,输出内容如下(输出格式见输入输出示例):
  • 各个图形的面积;
  • 所有图形的面积总和;
  • 排序后的各个图形面积;
  • 再次所有图形的面积总和
(1)源代码:
  1 //package pta;
  2 
  3 import java.util.Scanner;
  4 import java.util.ArrayList;
  5 
  6 //import java.util.Arrays;
  7 //import java.util.Collection;
  8 
  9 public class Main {
 10     public static void main(String[] args) {
 11         // TODO Auto-generated method stub
 12         Scanner in = new Scanner(System.in);
 13         int n1=in.nextInt(); int n2=in.nextInt(); int n3=in.nextInt();
 14         if(n1<0||n2<0||n3<0){
 15             System.out.println("Wrong Format");
 16             System.exit(0);
 17         }
 18         double sums = 0;
 19         ArrayList al=new ArrayList<>();
 20         
 21         for(int i=0;i//圆形加入数组表
 22             double radius=in.nextDouble();
 23             Circle circle=new Circle(radius);
 24             al.add(circle);
 25         }
 26         for(int i=n1;i//矩形加入数组表
 27             double width=in.nextDouble();
 28             double length=in.nextDouble();
 29             Rectangle rectangle=new Rectangle(width,length);
 30             al.add(rectangle);
 31         }
 32         for(int i=n1+n2;i//三角形加入数组表
 33             double side1=in.nextDouble();
 34             double side2=in.nextDouble();
 35             double side3=in.nextDouble();
 36             Triangle triangle=new Triangle(side1,side2,side3);
 37             al.add(triangle);
 38         }
 39         
 40         for(int i=0;i//检验数据合法性
 41             if(!al.get(i).validate())    {
 42                 System.out.println("Wrong Format");
 43                 System.exit(0);
 44             }
 45         }
 46         System.out.println("Original area:");//输出各图形面积
 47         for(int i=0;i) {
 48             sums+=al.get(i).getArea();
 49             System.out.print(String.format("%.2f",al.get(i).getArea())+" ");
 50         }
 51         System.out.println("\nSum of area:"+(String.format("%.2f",sums)));//输出总面积
 52         sort(al);//图形根据面积大小排序
 53         System.out.println("Sorted area:");//输出各排序后图形面积
 54         sums=0;
 55         for(int i=0;i) {
 56             sums+=al.get(i).getArea();
 57             System.out.print(String.format("%.2f",al.get(i).getArea())+" ");
 58         }
 59         System.out.print("\nSum of area:"+(String.format("%.2f",sums)));//输出总面积
 60     }
 61     private static void sort(ArrayList w) {
 62         // TODO Auto-generated method stub
 63         for(int i=0;i) {
 64             int index=i;
 65             for(int j=i+1;j) {
 66                 if(w.get(j).getArea()j;
 67             }
 68             if(index!=i)    swap(w,i,index);
 69         }
 70     }
 71     private static void swap(ArrayList a,int x,int y) {
 72         Shape temp=a.get(x);
 73         a.set(x, a.get(y));
 74         a.set(y, temp);
 75     }
 76 }
 77 abstract class Shape{
 78     
 79     Shape(){//构造方法
 80         
 81     }
 82     abstract double getArea();
 83     abstract boolean validate();
 84     //toString继承自Object,功能为输出图形的面积信息
 85     public String toString() {
 86         return null;
 87     }
 88 }
 89 class Circle extends Shape{
 90     double radius;
 91     
 92     Circle(){//无参构造方法
 93         
 94     }
 95     Circle(double radius){//带参构造方法
 96         this.radius=radius;
 97     }
 98     @Override
 99     double getArea() {
100         // TODO Auto-generated method stub
101         return Math.PI*Math.pow(radius, 2);
102     }
103     @Override
104     boolean validate() {
105         // TODO Auto-generated method stub
106         if(radius>0)    return true;
107         else    return false;
108     }
109 }
110 class Rectangle extends Shape{
111     double width,length;
112     
113     Rectangle(){
114         
115     }
116     Rectangle(double width,double length){
117         this.width=width;
118         this.length=length;
119     }
120     @Override
121     double getArea() {
122         // TODO Auto-generated method stub
123         return width*length;
124     }
125     @Override
126     boolean validate() {
127         // TODO Auto-generated method stub
128         if(width>0&&length>0)        return true;
129         else    return false;
130     }
131 }
132 class Triangle extends Shape{
133     double side1,side2,side3;
134     
135     Triangle(){
136         
137     }
138     Triangle(double side1,double side2,double side3){
139         this.side1=side1;
140         this.side2=side2;
141         this.side3=side3;
142     }
143     @Override
144     double getArea() {
145         // TODO Auto-generated method stub
146         double p=0.5*(side1+side2+side3);
147         return Math.sqrt(p*(p-side1)*(p-side2)*(p-side3));
148     }
149     @Override
150     boolean validate() {
151         // TODO Auto-generated method stub
152         double a=side1;double b=side2;double c=side3;
153         //任意两边之和大于第三边,任意两边之差小于第三边
154         if(a>0&&b>0&&c>0&&a+b>c&&a+c>b&&b+c>a&&a-breturn true;
155         else    return false;
156     }
157 }
(2)SourceMonitor的生成报表内容

 

(3)PowerDesigner的相应类图
(4)解释和心得:

主类Main中包含main主方法和一个排序方法,主要用途是接收输入和按照题目要求提供相应输出。首先分别接收n1、n2和n3,分别为圆形、矩形和三角形三种图形的数量,接收到三种图形数量后则分别构建相应数量的图形实体类,并按照先后顺序分别存储在数组链表ArrayList中(每一个数组链表单位空间中存储了一个图形实体类,图形的属性有输入中获取并立即进行属性参数设置然后构建图形实体)。之后,分别按顺序输出各图形的面积,并输出所有图形相加的总面积。再将存储在数组链表中的各个图形实体根据图形面积大小(从小到大)进行排序(即调换图形实体在数组链表中所处的位置,而不是计算出各个图形实体的面积再将面积进行排序最后输出),最后按照排序后的顺序分别输出各图形的面积,并输出所有图形相加的总面积。

 抽象类Shape(图形类),用作图形父类,其中包含构造方法和两个抽象方法getArea()和validate()以及方法toString()。

子类Circle(圆形类)继承于抽象类Shape,继承了两个抽象方法getArea()和validate(),并分别改写其方法,返回了圆形的面积和判断了圆形属性radius(半径)的合法性。新定义了私有属性radius(半径),并且包含两种构造方法(默认构造方法和带参构造方法)。

子类Rectangle(矩形类)继承于抽象类Shape,继承了两个抽象方法getArea()和validate(),并分别改写其方法,返回了矩形的面积和判断了矩形属性width(宽)和length(长)的合法性。新定义了私有属性width(宽)和length(长),并且包含两种构造方法(默认构造方法和带参构造方法)。

子类Triangle(三角形类)继承于抽象类Shape,继承了两个抽象方法getArea()和validate(),并分别改写其方法,返回了三角形的面积和判断了三角形属性side1、side2、side3(三边)的合法性。新定义了私有属性side1、side2、side3(三边),并且包含两种构造方法(默认构造方法和带参构造方法)。

  • 题目集6(7-6) 实现图形接口及多态性:编写程序,使用接口及类实现多态性。

其中:

  • GetArea为一个接口,无属性,只有一个GetArea(求面积)的抽象方法;
  • Circle及Rectangle分别为圆类及矩形类,分别实现GetArea接口
  • 要求:在Main类的主方法中分别定义一个圆类对象及矩形类对象(其属性值由键盘输入),使用接口的引用分别调用圆类对象及矩形类对象的求面积的方法,直接输出两个图形的面积值。(要求只保留两位小数)

输入格式:

从键盘分别输入圆的半径值及矩形的宽、长的值,用空格分开。

输出格式:

  • 如果输入的圆的半径值及矩形的宽、长的值非法(≤0),则输出Wrong Format
  • 如果输入合法,则分别输出圆的面积和矩形的面积值(各占一行),保留两位小数。
(1)源代码:
 1 //package pta;
 2 
 3 import java.util.Scanner;
 4 
 5 public class Main {
 6     public static void main(String[] args) {
 7         // TODO Auto-generated method stub
 8         Scanner in = new Scanner(System.in);
 9         double radius=in.nextDouble();
10         Circle circle=new Circle(radius);
11         double width=in.nextDouble();
12         double length=in.nextDouble();
13         Rectangle rectangle=new Rectangle(width,length);
14         
15         if(radius<=0||width<=0||length<=0)
16             System.out.print("Wrong Format");
17         else {
18             System.out.printf("%.2f\n",circle.getArea());
19             System.out.printf("%.2f\n",rectangle.getArea());
20         }
21     }
22 }
23 interface GetArea{
24     double getArea();
25 }
26 class Circle implements GetArea{
27     double radius;
28     
29     Circle(){
30         
31     }
32     Circle(double radius){
33         this.radius=radius;
34     }
35     double getRadius(){
36         return radius;
37     }
38     void setRadius(double radius) {
39         this.radius=radius;
40     }
41     @Override
42     public double getArea() {
43         // TODO Auto-generated method stub
44         return Math.PI*Math.pow(radius,2);
45     }
46 }
47 class Rectangle implements GetArea{
48     double width,length;
49     
50     Rectangle(){
51         
52     }
53     Rectangle(double width,double length){
54         this.width=width;
55         this.length=length;
56     }
57     double getWidth() {
58         return width;
59     }
60     void setWidth(double width) {
61         this.width=width;
62     }
63     double getLength() {
64         return length;
65     }
66     void setLength(double length) {
67         this.length=length;
68     }
69     @Override
70     public double getArea() {
71         // TODO Auto-generated method stub
72         return width*length;
73     }
74 }
(2)SourceMonitor的生成报表内容

 

(3)PowerDesigner的相应类图

 

(4)解释和心得:

主类Main中仅包含main主方法,主要用途是接收输入并根据题目要求输出相应结果。分别接收了圆的半径和矩形的宽和长,构建了圆形和矩形两个图形实体类。判断输入数据合法性,若有误则打印“Wrong Format”。最后调用Circle类和Rectangle类中getArea()方法计算图形面积并分别输出。

接口interface GetArea(计算图形面积)中包含getArea()方法。

类Circle(圆形类)实现于接口GetArea,包含getArea方法,重写该方法返回计算出的圆形面积。新定义私有属性radius(半径),可对其进行返回参数和设置参数操作。包含一个默认构造方法。

类Rectangle(矩形类)实现于接口GetArea,包含getArea方法,重写该方法返回计算出的矩形面积。新定义私有属性width(宽)和length(长),可对其进行返回参数和设置参数操作。包含一个默认构造方法。

3.三次题目集中用到的正则表达式技术的分析总结

 这三次题目集中涉及到正贼表达式技术应用的题:4-7_1-水文数据校验及处理、5-7_2-统计Java程序中关键词的出现次数以及第六次题目集前四道正则表达式基础训练题。

其中涉及到的知识点包括:正则表达式的书写格式及其相关含义,append()去除空格方法、split()分割方法、Pattern()和matcher()模式匹配方法等相关方法的使用。

4.Java集合框架应用的分析总结

  • 题目集5(7-5):日期问题面向对象设计(聚合二),设计类图如下:

(1)源代码及SourceMonitor的生成报表内容见上;

(2)解释与心得:这部分主要围绕Java集合框架应用的分析总结来展开描述。

main类中包含main函数,主要用途是接收输入的数据,并通过调用类DateUtil中一些具体的方法实现题目的具体要求(像求当前日期后\前N天的日期、求两个日期之间的天数),可以通过输入选项编号1~3来选择程序计算进入以上三种的哪一种。除此之外,通过调用类DateUtil中的checkInputValidity方法以及自检输入选项编号的检测,实现对输入数据合法性的检测判断,若输入有误则打印Wrong Format;

DateUtil类中包含一个实体类Day day、两种自身的构造方法(默认构造方法和带参构造方法)以及一系列具体的日期相关处理方法(像前面提到的校验数据合法性checkInputValidity()、比较两个日期大小compareDates()、判定两个日期是否相等equalTwoDates()以及求当前日期后\前N天的日期、求两个日期之间的天数等等),同时它还可以对实体类Day进行一些操作,比如返回day的值或者设置day的值。总体来讲日期处理类是整个程序设计的核心部分,各种所需的操作方法大都聚合于此。

剩下部分则是三个日期类:Day类、Month类、Year类。它们分别包含了一些自己私有的属性和方法,像自己的参数值,返回自身的值或者设置自身的值,检测自身参数值的合法性,加一减一以及设为最大值或最小值等等。值得一提的是,在这次日期问题面向对象设计方案中,Day类中包含有一个month实体类,Month类中包含有一个year实体类,即在DateUtil类中,可通过调用类Day再调用类Month最后调用类Year,实现对Year类中的属性和方法的访问和调用。

三、总结:

    由于本阶段三次题目集不太少的题目量和不太小的题目难度,这三周的作业涉及的知识点也比较多,有的是课堂上学习过的做一个实践应用,有的则是在网上查阅相关的资料和例题,边模仿边学习。当然,也因此这三周的收获也会比上个三周的大很多。

    第一点收获当然是对面向对象的程序设计思维的理解更加深入深刻了。现阶段能够更深刻理解什么叫面向对象程序设计以及面向对象程序设计的好处,也慢慢理解了老师在刚开课时跟我们讲的对于一些比较小的工程面向过程也许会更方便快捷,但对于较大的工程面向对象程序设计天然地具有更大的优势。通过两次日期问题(聚合一)(聚合二)的实践,我心里对于构建类之间关系体系框架的构建有了一个初步的认识和理解,也了解到有一个清晰明确的框架对于处理比较多的问题时的优点。两种框架构建方法的对比让我也体会到实体类调用具体方法的方便快捷。

    第二点收获则是对于封装、继承、多态以及接口的理解。封装的目的是:增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,一特定的访问权限来使用类的成员。继承的目的是实现代码的复用。多态的概念是相同的事物,调用其相同的方法,参数也相同时,但表现的行为却不同。Java实现多态有三个必要条件:继承、重写、向上转型。多态的实现方式分为基于继承实现和基于接口实现。一个接口可以被多个类实现,一个类也可以实现多个接口。(接口的实现可以理解为弥补Java中没有多个父类的缺陷)。接口中的方法都是抽象的方法,并且抽象的方法默认都是public abstract修饰的,不能用其他的修饰符修饰,可以不写。接口不是类,因此接口中不存在构造方法。除此之外还有抽象类和抽象方法的概念,被abstract修饰的方法是抽象方法,抽象方法没有方法体。修饰符 abstract 返回值类型 函数名();抽象方法的修饰符只能用public或者protected或者没有修饰,不能被final,static,private修饰。

    第三点收获是正则表达式相关技术和方法的学习和使用。正则表达式的书写格式及其相关含义,append()去除空格方法、split()分割方法、Pattern()和matcher()模式匹配方法等相关方法的使用。

    最后总结,自己对于正则表达式相关知识点的掌握感觉还不够,需要进一步的学习、练习和实践。