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] 。
应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
(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] 。
应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
(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 //y1251 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() 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;ireturn a[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;i a[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) 图形继承:
编写程序,实现图形类的继承,并定义相应类对象并进行测试。
- 类Shape,无属性,有一个返回0.0的求图形面积的公有方法
public double getArea();//求图形面积
- 类Circle,继承自Shape,有一个私有实型的属性radius(半径),重写父类继承来的求面积方法,求圆的面积
- 类Rectangle,继承自Shape,有两个私有实型属性width和length,重写父类继承来的求面积方法,求矩形的面积
- 类Ball,继承自Circle,其属性从父类继承,重写父类求面积方法,求球表面积,此外,定义一求球体积的方法
public double getVolume();//求球体积
- 类Box,继承自Rectangle,除从父类继承的属性外,再定义一个属性height,重写父类继承来的求面积方法,求立方体表面积,此外,定义一求立方体体积的方法
public double getVolume();//求立方体体积
- 注意:
- 每个类均有构造方法,且构造方法内必须输出如下内容:
Constructing 类名
- 每个类属性均为私有,且必须有getter和setter方法(可用Eclipse自动生成)
- 输出的数值均保留两位小数
主方法内,主要实现四个功能(1-4): 从键盘输入1,则定义圆类,从键盘输入圆的半径后,主要输出圆的面积; 从键盘输入2,则定义矩形类,从键盘输入矩形的宽和长后,主要输出矩形的面积; 从键盘输入3,则定义球类,从键盘输入球的半径后,主要输出球的表面积和体积; 从键盘输入4,则定义立方体类,从键盘输入立方体的宽、长和高度后,主要输出立方体的表面积和体积;
假如数据输入非法(包括圆、矩形、球及立方体对象的属性不大于0和输入选择值非1-4),系统输出
Wrong Format
- 类Shape,无属性,有一个返回0.0的求图形面积的公有方法
(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对象的数量,然后根据图形数量继续输入各对象的属性值(均为实型数),数与数之间可以用一个或多个空格或回车分隔。
输出格式:
- 如果图形数量非法(小于0)或图形属性值非法(数值小于0以及三角形三边关系),则输出
Wrong Format
。 - 如果输入合法,则正常输出,输出内容如下(输出格式见输入输出示例):
- 各个图形的面积;
- 所有图形的面积总和;
- 排序后的各个图形面积;
- 再次所有图形的面积总和
(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 ArrayListal=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-b return 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()模式匹配方法等相关方法的使用。
最后总结,自己对于正则表达式相关知识点的掌握感觉还不够,需要进一步的学习、练习和实践。