Blog總結02(4~6次作業總結)
- 2021 年 5 月 2 日
- 筆記
Blog總結02(4~6次作業總結)
1.前言
(1)題目集04共有三道題目,第一題難度較大,第二題和第三題難度適中,第一題考察的知識點是 Java 中的字元串處理類以及正則表達式對輸入字元串數據進行合法性校驗及計算,難度較大。第二題考察對日期的處理,熟悉面向對象的學習,創建多個類,然後將其中一個類的創建的對象黨當作另一個對象的屬性,考察了在其他類中創建對象和調用其他類的方法,含參數不含參數的構造方法,getset的構造方法的使用,屬性私有性的知識點等,第三題是圖形繼承題目,難度適中,考察了繼承的知識點,弄清楚子類父類的關係,子類調用父類的方法,在子類中重寫父類的方法等知識點。
(2)題目集05共有五道題目,1~3題較為簡單,分別考察對字元串的處理,對數組的處理,對整型數據排序,第四題難度較大,統計Java程式中關鍵詞的出現次數,知識點為利用正則表達式對字元進行匹配以及對字元串的處理,第五題難度適中,考察了在其他類中創建對象和調用其他類的方法,含參數不含參數的構造方法,getset的構造方法的使用,屬性私有性的知識點等,和題目集04第二題很相似但有一些區別。
(3)題目集06共有六道題目,其中1~4題較為簡單,1,3,4題考察了利用正則表達式去匹配字元串,2題考察了字元串與字元之間的轉換,以及排序,第五六題難度適中,第五題考察了類的繼承、多態性及其使用方法,讓我們了解抽象類和抽象方法,抽像類方法的調用等,還有一些ArrayList類和Collection類的使用,第六題知識點為介面的使用和類的多態性,用介面去調用方法實現功能。
2.設計與分析
(1)題目集04(7-2 )&&題目集05(7-5)
日期問題面向對象設計
應用程式共測試三個功能:
- 求下n天
- 求前n天
- 求兩個日期相差的天數
輸入格式:
有三種輸入方式(以輸入的第一個數字劃分[1,3]):
- 1 year month day n //測試輸入日期的下n天
- 2 year month day n //測試輸入日期的前n天
- 3 year1 month1 day1 year2 month2 day2 //測試兩個日期之間相差的天數
輸出格式:
-
當輸入有誤時,輸出格式如下:
Wrong Format
-
當第一個數字為1且輸入均有效,輸出格式如下:
year-month-day
-
當第一個數字為2且輸入均有效,輸出格式如下:
year-month-day
-
當第一個數字為3且輸入均有效,輸出格式如下:
天數值
題目集04(7-2)源碼如下:
1 import java.util.Scanner; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 Scanner input = new Scanner(System.in); 7 int n = input.nextInt(); 8 if(n >= 1 && n <= 3) { 9 int x = input.nextInt(); 10 int y = input.nextInt(); 11 int z = input.nextInt(); 12 DateUtil date = new DateUtil(x,y,z); 13 14 if(y>12||y<1) 15 System.out.println("Wrong Format"); 16 else { 17 if(date.checkInputValidity()) { 18 switch(n) { 19 case 1: 20 date.getNextNdate(input.nextInt()); 21 System.out.println(date.showDate()); 22 break; 23 case 2: 24 date.getPreviousNDays(input.nextInt()); 25 System.out.println(date.showDate()); 26 break; 27 case 3: 28 int a = input.nextInt(); 29 int b = input.nextInt(); 30 int c = input.nextInt(); 31 DateUtil date2 = new DateUtil(a,b,c); 32 if(b>12||b<1) 33 System.out.println("Wrong Format"); 34 else { 35 System.out.println(date.getDaysofDates(date2)); 36 date.getDaysofDates(date2); 37 break;} 38 } 39 40 } 41 else 42 System.out.println("Wrong Format"); 43 } 44 45 } 46 else 47 System.out.println("Wrong Format"); 48 } 49 } 50 51 52 53 class Year{ 54 private int value; 55 56 public Year() { 57 super(); 58 } 59 60 public Year(int value) { 61 super(); 62 this.value = value; 63 } 64 65 public int getValue() { 66 return value; 67 } 68 69 public void setValue(int value) { 70 this.value = value; 71 } 72 public boolean isLeapYear() { 73 if ((this.value % 4 == 0 && this.value % 100 != 0 )|| this.value % 400 == 0) 74 return true; 75 else 76 return false; 77 } 78 public boolean validate() { 79 if(getValue() >= 1900 && getValue() <= 2050 ) 80 return true; 81 else 82 return false; 83 } 84 public void yearIncrement() { 85 this.value ++; 86 } 87 public void yearReduction() { 88 this.value --; 89 } 90 } 91 92 class Month{ 93 private int value; 94 private Year year = new Year(); 95 96 public Month() { 97 super(); 98 } 99 100 public Month(int yearValue, int monthValue) { 101 this.year.setValue(yearValue); 102 this.value = monthValue ; 103 104 } 105 106 public int getValue() { 107 return value; 108 } 109 110 public void setValue(int value) { 111 this.value = value; 112 } 113 114 public Year getYear() { 115 return year; 116 } 117 118 public void setYear(Year year) { 119 this.year = year; 120 } 121 122 public void resetMin() { 123 this.value = 1; 124 } 125 126 public void resetMax() { 127 this.value = 12; 128 } 129 130 public boolean validate() { 131 if(year.validate() && this.value >= 1 && this.value <= 12) 132 return true; 133 else 134 return false; 135 } 136 137 public void monthIncrement() { 138 if(this.value == 12) { 139 year.yearIncrement(); 140 resetMin(); 141 } 142 else 143 this.value ++; 144 } 145 146 public void monthReduction() { 147 if(this.value == 1) { 148 year.yearReduction(); 149 resetMax(); 150 } 151 else 152 this.value --; 153 } 154 155 } 156 157 class Day{ 158 private int value; 159 private Month month = new Month(); 160 private int [] mon_maxnum = {31,28,31,30,31,30,31,31,30,31,30,31}; 161 162 public Day() { 163 164 } 165 166 public Day(int yearValue,int monthValue,int dayValue) { 167 this.month.getYear().setValue(yearValue); 168 this.month.setValue(monthValue); 169 this.value = dayValue; 170 171 } 172 173 public int getValue() { 174 return value; 175 } 176 177 public void setValue(int value) { 178 this.value = value; 179 } 180 181 public Month getMonth() { 182 return month; 183 } 184 185 public void setMonth(Month month) { 186 this.month = month; 187 } 188 189 public void resetMin() { 190 this.value = 1; 191 } 192 public void resetMax() { 193 this.value = getMaxOfmonth(); 194 } 195 public void resetMMax() { 196 switch (month.getValue()) { 197 case 1:this.value = mon_maxnum[0];break; 198 case 2: 199 if(month.getYear().isLeapYear()) { 200 this.value = mon_maxnum[1] + 1; 201 } 202 else 203 this.value = mon_maxnum[1]; 204 break; 205 case 3:this.value = mon_maxnum[2];break; 206 case 4:this.value = mon_maxnum[3];break; 207 case 5:this.value = mon_maxnum[4];break; 208 case 6:this.value = mon_maxnum[5];break; 209 case 7:this.value = mon_maxnum[6];break; 210 case 8:this.value = mon_maxnum[7];break; 211 case 9:this.value = mon_maxnum[8];break; 212 case 10:this.value = mon_maxnum[9];break; 213 case 11:this.value = mon_maxnum[10];break; 214 case 12:this.value = mon_maxnum[11];break; 215 default:;break; 216 } 217 } 218 public int getMaxOfmonth() { 219 if(month.getYear().isLeapYear() && month.getValue() == 2) 220 return 29; 221 else 222 return mon_maxnum[month.getValue()-1]; 223 } 224 public int returnMonthMax() { 225 switch (month.getValue()) { 226 case 1:return mon_maxnum[0]; 227 case 2: 228 if(month.getYear().isLeapYear()) { 229 return mon_maxnum[1]; 230 } 231 else 232 return mon_maxnum[1] + 1; 233 234 case 3:return mon_maxnum[2]; 235 case 4:return mon_maxnum[3]; 236 case 5:return mon_maxnum[4]; 237 case 6:return mon_maxnum[5]; 238 case 7:return mon_maxnum[6]; 239 case 8:return mon_maxnum[7]; 240 case 9:return mon_maxnum[8]; 241 case 10:return mon_maxnum[9]; 242 case 11:return mon_maxnum[10]; 243 case 12:return mon_maxnum[11]; 244 default:;break; 245 } 246 return 0; 247 } 248 public boolean validate(){ 249 if(month.validate()&&this.value <= getMaxOfmonth()&&this.value >= 1 ) 250 return true; 251 else 252 return false; 253 } 254 255 public void dayIncrement() { 256 if(this.value == getMaxOfmonth()) { 257 month.monthIncrement(); 258 resetMin(); 259 } 260 else 261 this.value ++; 262 } 263 public void dayReduction() { 264 if(this.value == 1) { 265 month.monthReduction(); 266 resetMax(); 267 } 268 else 269 this.value --; 270 } 271 } 272 273 274 275 276 class DateUtil{ 277 private Day day = new Day(); 278 279 public DateUtil() { 280 super(); 281 } 282 public DateUtil(int y,int m, int d) { 283 day.getMonth().getYear().setValue(y); 284 day.getMonth().setValue(m); 285 day.setValue(d); 286 } 287 public Day getDay() { 288 return day; 289 } 290 public void setDay(Day day) { 291 this.day = day; 292 } 293 public boolean checkInputValidity() { 294 if(day.getMonth().getYear().validate() && day.getMonth().validate() && day.validate()) 295 return true; 296 else 297 return false; 298 } 299 300 public String showDate() { 301 return this.day.getMonth().getYear().getValue()+"-"+this.day.getMonth().getValue()+"-"+this.day.getValue(); 302 } 303 304 public boolean compareDates(DateUtil date) { 305 int a = date.day.getMonth().getYear().getValue()*20000+date.day.getMonth().getValue()*1000+date.day.getValue(); 306 int b = this.day.getMonth().getYear().getValue()*20000+this.day.getMonth().getValue()*1000+this.day.getValue(); 307 if(a<b) 308 return false; 309 else 310 return true; 311 } 312 313 public boolean equalTwoDates(DateUtil date) { 314 if(date.showDate().equals(showDate())) 315 return true; 316 else 317 return false; 318 } 319 320 public DateUtil getNextNdate(int n) { 321 for(int i = 0; i < n ; i++) { 322 day.dayIncrement(); 323 } 324 return new DateUtil (day.getMonth().getYear().getValue(),day.getMonth().getValue(),day.getValue()); 325 } 326 327 public DateUtil getPreviousNDays(int n) { 328 for(int i = 0; i < n; i ++) { 329 day.dayReduction(); 330 } 331 return new DateUtil (day.getMonth().getYear().getValue(),day.getMonth().getValue(),day.getValue()); 332 } 333 334 public int getDaysofDates(DateUtil date){ 335 int number = 0; 336 if(compareDates(date)){ 337 for(; !equalTwoDates(date); ) { 338 date.day.dayReduction(); 339 number ++; 340 } 341 } 342 else if(!compareDates(date)){ 343 for(;!equalTwoDates(date);) { 344 date.day.dayIncrement(); 345 number ++; 346 } 347 } 348 return number; 349 350 } 351 }
題目集05(7-5)源程式碼:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int n = input.nextInt(); if(n > 3 || n < 1) System.out.println("Wrong Format"); else { int x = input.nextInt(); int y = input.nextInt(); int z = input.nextInt(); DateUtil date = new DateUtil(x,y,z); if(date.checkInputValidate()) { switch(n) { case 1: int days1 = input.nextInt(); date.getNextNdate(days1); System.out.println(x+"-"+y+"-"+z+" next "+days1+" days is:"+date.showDate()); break; case 2: int days2 = input.nextInt(); date.getPreviousNDays(days2); System.out.println(x+"-"+y+"-"+z+" previous "+days2+" days is:"+date.showDate()); break; case 3: int a = input.nextInt(); int b = input.nextInt(); int c = input.nextInt(); DateUtil date2 = new DateUtil(a,b,c); if(date2.checkInputValidate()) { System.out.println("The days between "+date.showDate()+" and "+date2.showDate()+" are:"+date.getDaysofDates(date2)); break; } } } else System.out.println("Wrong Format"); } } } class Year{ private int value; public Year() { super(); } public Year(int value) { super(); this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public boolean isLeapYear() { if ((this.value % 4 == 0 && this.value % 100 != 0 )|| this.value % 400 == 0) return true; else return false; } public boolean validate() { if(getValue() >= 1820 && getValue() <= 2020 ) return true; else return false; } public void yearIncrement() { this.value ++; } public void yearReduction() { this.value --; } } class Month{ private int value; public Month() { super(); } public Month( int Value) { this.value = Value ; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public void resetMin() { this.value = 1; } public void resetMax() { this.value = 12; } public boolean validate() { if(this.value >= 1 && this.value <= 12) return true; else return false; } public void monthIncrement() { this.value ++; } public void monthReduction() { this.value --; } } class Day{ private int value; public Day() { } public Day(int value) { super(); this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public void dayIncrement() { this.value ++; } public void dayReduction() { this.value --; } } class DateUtil{ private Year year = new Year(); private Month month = new Month(); private Day day = new Day(); private int [] mon_maxnum = {31,28,31,30,31,30,31,31,30,31,30,31}; public DateUtil() { super(); } public DateUtil(int y,int m,int d) { super(); year.setValue(y); month.setValue(m); day.setValue(d); } public Year getYear() { return year; } public void setYear(Year year) { this.year = year; } public Month getMonth() { return month; } public void setMonth(Month month) { this.month = month; } public Day getDay() { return day; } public void setDay(Day day) { this.day = day; } private void setDayMin() { day.setValue(1); } private void setDayMax() { day.setValue(getDayMax()); } public int getDayMax() { if(year.isLeapYear() && month.getValue() == 2) { return 29; } else { return mon_maxnum[month.getValue()-1]; } } public boolean checkInputValidate() { if(year.validate() && month.validate()) { if(day.getValue() >= 1 && day.getValue() <= getDayMax() ) return true; else return false; } else return false; } public DateUtil getNextNdate(long n) { for(int i = 0; i < n ; i ++ ) { if(month.getValue() == 12 && day.getValue() == 31) { month.resetMin(); setDayMin(); year.yearIncrement(); } else if(day.getValue() == getDayMax()) { day.setValue(1); month.monthIncrement(); } else day.dayIncrement(); } return new DateUtil(year.getValue(),month.getValue(),day.getValue()); } public DateUtil getPreviousNDays(long n) { for(int i = 0; i < n ; i ++ ) { if(month.getValue() == 1 && day.getValue() == 1) { year.yearReduction(); month.resetMax(); setDayMax(); } else if(day.getValue() == 1) { month.monthReduction(); setDayMax(); } else day.dayReduction(); } return new DateUtil(year.getValue(),month.getValue(),day.getValue()); } public int getDaysofDates(DateUtil date) { int num = 0; if(equalTwoDates( date)) return 0; if(compareDates( date)) { for(;!equalTwoDates( date);) { if(month.getValue() == 12 && day.getValue() == 31) { month.resetMin(); setDayMin(); year.yearIncrement(); } else if(day.getValue() == getDayMax()) { day.setValue(1); month.monthIncrement(); } else day.dayIncrement(); num ++; } } else if(!compareDates( date)) { for(;!equalTwoDates( date);) { if(month.getValue() == 1 && day.getValue() == 1) { year.yearReduction(); month.resetMax(); setDayMax(); } else if(day.getValue() == 1) { month.monthReduction(); setDayMax(); } else day.dayReduction(); num ++; } } return num; } public boolean compareDates(DateUtil date) { int a = date.year.getValue()*20000+date.month.getValue()*1000+date.day.getValue(); int b = this.year.getValue()*20000+this.month.getValue()*1000+this.day.getValue(); if(a > b) return true; else return false; } public boolean equalTwoDates(DateUtil date) { if(date.showDate().equals(showDate())) return true; else return false; } public String showDate() { return year.getValue()+"-"+month.getValue()+"-"+day.getValue(); } }
SourceMonitor的生成報表內容:
題目集04(7-2):
題目集05(7-5):
類圖:
題目集04(7-2):
題目集05(7-5):
根據SourceMonitor的生成報表可以看到兩個程式的圈複雜程度相差不大,這兩道題相比之前的日期類題目,圈複雜度已經大大的降低了,再根據類圖來分析兩個程式的不同,首先第一個程式是遞進式的聚合,一環套一環,year類最先寫,然後在month類中創建了一個year類的對象當作month類的一個屬性,然後在day類中又創建了一個month對象作為day類中的屬性,最後在日期處理類中創建了一個day的對象當作它的屬性,整體來說就是一環扣一環,不可分割,第二個程式year,month,day等類是分開的,他們之間並沒有聯繫,由一個日期處理類將他們聯繫在一起。
優劣分析:
我認為第一個程式的聚合耦合度非常的高,因為環環相扣,他的劣勢在於,如果其中某個環節除了錯誤,很難改正,尤其是到後面才發現錯誤,就可能要把整個程式都改一下,類與類之間的關係太緊密了,每當要用到year的方法,需要從DateUtil調用day再調用month再調用year,調用起來也比較複雜,但是它也有他的優點,到最後實現前n天或者後n天的時候,它只需要調用一個day的加減就可以了,因為之前做了鋪墊,程式的邏輯就比較簡單了。
我認為第二個程式總體來說應該是優於第一個程式的,首先它的年月日的類是分開的,它們之間是沒有直接的關係的,耦合程度非常的低,就算我其中一個類出錯了,和其他的類也沒有什麼關係,而且出錯之後非常的好修改,也知道錯在哪裡,而他得缺點就是到最後的日期處理類中,我們需要進行一些思考,去完成前n天后n天的實現,我們知道,java類與類之間的耦合程度越低越好,且第二個程式很好的保證了類的單一職責的原則,所以我認為第二個程式總體來說比第一個好一些。
(2)題目集04(7-3)題目集06(7-5、7-6)
題目集04(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
輸入格式:
共四種合法輸入
- 1 圓半徑
- 2 矩形寬、長
- 3 球半徑
- 4 立方體寬、長、高
輸出格式:
按照以上需求提示依次輸出
源碼如下:
1 import java.util.Scanner; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 Scanner input = new Scanner(System.in); 7 int n = input.nextInt(); 8 if(n > 4 || n < 1) { 9 System.out.println("Wrong Format"); 10 System.exit(0); 11 } 12 13 switch(n){ 14 case 1: 15 16 double r = input.nextDouble(); 17 if(r < 0) { 18 System.out.println("Wrong Format"); 19 System.exit(0);} 20 else { 21 Circle c = new Circle(); 22 c.setRadius(r); 23 System.out.println("Circle's area:"+String.format("%.2f", c.getArea())); 24 } 25 break; 26 case 2: 27 28 double chang = input.nextDouble(); 29 double kuan = input.nextDouble(); 30 if(chang < 0 ||kuan < 0) { 31 System.out.println("Wrong Format"); 32 System.exit(0); 33 } 34 else { 35 Rectangle zf = new Rectangle(); 36 zf.setLength(chang); 37 zf.setWidth(kuan); 38 System.out.println("Rectangle's area:"+String.format("%.2f", zf.getArea())); 39 }break; 40 case 3: 41 42 double R = input.nextDouble(); 43 if(R < 0) { 44 System.out.println("Wrong Format"); 45 System.exit(0); 46 } 47 else { 48 Ball b = new Ball(); 49 b.setRadius(R); 50 System.out.println("Ball's surface area:"+String.format("%.2f", b.getArea())); 51 System.out.println("Ball's volume:"+String.format("%.2f",b.getVolume() )); 52 } 53 break; 54 case 4: 55 56 double ch = input.nextDouble(); 57 double ku = input.nextDouble(); 58 double gao = input.nextDouble(); 59 if(ch < 0 || ku < 0 || gao < 0) { 60 System.out.println("Wrong Format"); 61 System.exit(0); 62 } 63 else { 64 Box B = new Box(); 65 B.setLength(ch); 66 B.setWidth(ku); 67 B.setHeight(gao); 68 System.out.println("Box's surface area:"+String.format("%.2f",B.getArea() )); 69 System.out.println(String.format("Box's volume:"+"%.2f",B.getVolume() )); 70 } 71 break; 72 default:; 73 } 74 } 75 76 77 private static void Switch(int n) { 78 // TODO 自動生成的方法存根 79 80 } 81 } 82 class Shape{ 83 public Shape() { 84 super(); 85 System.out.println("Constructing Shape"); 86 } 87 public double getArea() { 88 return 0.0; 89 } 90 } 91 class Circle extends Shape{ 92 private double radius; 93 94 public double getArea() { 95 return Math.PI*Math.pow(this.getRadius(), 2); 96 } 97 public Circle() { 98 super(); 99 System.out.println("Constructing Circle"); 100 } 101 public double getRadius() { 102 return radius; 103 } 104 public void setRadius(double radius) { 105 this.radius = radius; 106 } 107 108 } 109 class Rectangle extends Shape{ 110 private double width ; 111 private double length; 112 113 public double getWidth() { 114 return width; 115 } 116 117 public void setWidth(double width) { 118 this.width = width; 119 } 120 121 public double getLength() { 122 return length; 123 } 124 125 public void setLength(double length) { 126 this.length = length; 127 } 128 129 public double getArea() { 130 return this.length*this.width; 131 } 132 133 public Rectangle() { 134 super(); 135 System.out.println("Constructing Rectangle"); 136 } 137 } 138 class Ball extends Circle{ 139 140 public Ball() { 141 super(); 142 System.out.println("Constructing Ball"); 143 144 } 145 public double getArea() { 146 return 4*Math.PI*getRadius()*getRadius(); 147 } 148 149 public double getVolume() { 150 return 4.0/3*Math.PI*getRadius()*getRadius()*getRadius(); 151 } 152 } 153 class Box extends Rectangle{ 154 private double height; 155 156 public double getHeight() { 157 return height; 158 } 159 public void setHeight(double height) { 160 this.height = height; 161 } 162 public double getArea() { 163 return 2*(getWidth()*getLength()+getWidth()*this.height+getLength()*this.height); 164 } 165 public double getVolume() { 166 return this.height*getLength()*getWidth(); 167 } 168 169 public Box() { 170 super(); 171 System.out.println("Constructing Box"); 172 } 173 174 }
SourceMonitor的生成報表內容:
類圖如下:
題目集06(7-5):
掌握類的繼承、多態性及其使用方法。
輸入格式:
從鍵盤首先輸入三個整型值(例如a b c),分別代表想要創建的Circle、Rectangle及Triangle對象的數量,然後根據圖形數量繼續輸入各對象的屬性值(均為實型數),數與數之間可以用一個或多個空格或回車分隔。
輸出格式:
-
如果圖形數量非法(小於0)或圖形屬性值非法(數值小於0以及三角形三邊關係),則輸出
Wrong Format
。 -
如果輸入合法,則正常輸出,輸出內容如下(輸出格式見輸入輸出示例):
-
各個圖形的面積;
-
所有圖形的面積總和;
-
排序後的各個圖形面積;
-
再次所有圖形的面積總和。
源碼如下:
import java.util.ArrayList; import java.util.Collections; import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner input = new Scanner(System.in); int a = input.nextInt(); int b = input.nextInt(); int c = input.nextInt(); if(a < 0 || b < 0 || c < 0) System.out.println("Wrong Format"); else { Circle [] cir = new Circle[a]; Rectangle [] rec = new Rectangle[b]; Triangle [] tri = new Triangle[c]; ArrayList <Shape> list = new ArrayList<Shape>(); for(int i = 0; i < a; i ++) { cir [i] = new Circle(input.nextDouble()); if(cir[i].validate() == false) { System.out.println("Wrong Format"); System.exit(0); } list.add(cir[i]); } for(int i = 0; i < b ; i ++) { rec[i] = new Rectangle(input.nextDouble(),input.nextDouble()); if(rec[i].validate() == false) { System.out.println("Wrong Format"); System.exit(0); } list.add(rec[i]); } for(int i = 0; i < c; i ++) { tri[i] = new Triangle(input.nextDouble(),input.nextDouble(),input.nextDouble()); if(tri[i].validate() == false) { System.out.println("Wrong Format"); System.exit(0); } list.add(tri[i]); } double sum = 0; System.out.println("Original area:"); for(int i =0; i < a+b+c; i ++) { System.out.printf(String.format("%.2f", list.get(i).getArea()).toString()+" "); sum = sum + list.get(i).getArea(); } System.out.println("\n"+"Sum of area:"+String.format("%.2f", sum).toString()); for(int i = 0; i < a+b+c - 1; i++) for(int j = 0; j < a + b + c - 1 - i;j ++) { if(list.get(j).getArea() > list.get(j+1).getArea()) Collections.swap(list, j, j+1); } System.out.println("Sorted area:"); for(int i =0; i < a+b+c; i ++) { System.out.print(String.format("%.2f", list.get(i).getArea()).toString()+" "); } System.out.print("\n"+"Sum of area:"+String.format("%.2f", sum).toString()); } //System.out.println(String.format("%.2f", r.getArea()).toString()); } } abstract class Shape { public abstract double getArea(); public abstract boolean validate(); //@Override /*public String toString() { return "Shape [getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString() + "]"; } */ } class Circle extends Shape{ private double radius; public Circle() { super(); } public Circle(double radius) { super(); this.radius = radius; } public double getArea() { return Math.PI*this.radius * this.radius ; } public boolean validate() { if(this.radius <= 0) return false; else return true; } } class Rectangle extends Shape{ private double width; private double length; public Rectangle() { super(); // TODO 自動生成的構造函數存根 } public Rectangle(double width, double length) { super(); this.width = width; this.length = length; } public double getArea() { return this.length *this.width; } public boolean validate() { if(this.length > 0 && this.width > 0) return true; else return false; } } class Triangle extends Shape{ private double side1; private double side2; private double side3; public Triangle() { super(); // TODO 自動生成的構造函數存根 } public Triangle(double side1, double side2, double side3) { super(); this.side1 = side1; this.side2 = side2; this.side3 = side3; } public double getArea() { double s = (this.side1 + this.side2 + this.side3)/2.0; return Math.sqrt(s * (s - this.side1) * (s - this.side2) * (s - this.side3)); } public boolean validate() { if(this.side1 > 0 && this.side2 > 0 && this.side3 > 0) { if(this.side1 + this.side2 > this.side3 && this.side1 + this.side3 > this.side2 && this.side2 + this.side3 > this.side1) return true; else return false; } else return false; } }
SourceMonitor的生成報表內容:
類圖如下:
題目集06(7-6):
編寫程式,使用介面及類實現多態性。
其中:
- GetArea為一個介面,無屬性,只有一個GetArea(求面積)的抽象方法;
- Circle及Rectangle分別為圓類及矩形類,分別實現GetArea介面
- 要求:在Main類的主方法中分別定義一個圓類對象及矩形類對象(其屬性值由鍵盤輸入),使用介面的引用分別調用圓類對象及矩形類對象的求面積的方法,直接輸出兩個圖形的面積值。(要求只保留兩位小數)
輸入格式:
從鍵盤分別輸入圓的半徑值及矩形的寬、長的值,用空格分開。
輸出格式:
- 如果輸入的圓的半徑值及矩形的寬、長的值非法(≤0),則輸出
Wrong Format
- 如果輸入合法,則分別輸出圓的面積和矩形的面積值(各佔一行),保留兩位小數。
源碼如下:
import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner input = new Scanner(System.in); double x = input.nextDouble(); Circle c = new Circle(x); double y = input.nextDouble(); double z = input.nextDouble(); Rectangle r = new Rectangle(y,z); if(x <= 0 || y <= 0 || z <= 0) { System.out.println("Wrong Format"); System.exit(0); } System.out.println(String.format("%.2f", c.getArea()).toString()); System.out.println(String.format("%.2f", r.getArea()).toString()); } } class Circle implements GetArea{ private double radius; public Circle() { super(); } public Circle(double radius) { super(); this.radius = radius; } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } public double getArea() { return Math.PI*this.radius*this.radius; } } class Rectangle implements GetArea{ private double width; private double length; public Rectangle() { super(); } public Rectangle(double width, double length) { super(); this.width = width; this.length = length; } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public double getLength() { return length; } public void setLength(double length) { this.length = length; } public double getArea() { return this.length*this.width; } } interface GetArea{ public double getArea(); }
SourceMonitor的生成報表內容:
類圖如下:
這三道題都是繼承類題目,第一題要求我們求面積等,首先第一題有一個總的Shape類,一個圖形類,圖形可以包括很多種,它的子類包含了一個Circle類和Rectangle類,這裡的類都不是抽象類,是普通類,Shape類有一個getArea的方法,然後在Circle和Rectangle類中重寫了求面積的方法,在這個基礎上,又寫了兩個類Ball和Box分別繼承了Circle類和Rectangle類,Ball類和Box類中又重寫了求面積的方法,又增加了求體積的方法,每個類中都會輸出自己的類名,就是一旦跟這個類有關就會輸出這個類的類名,我覺得這道題更多是想幫助我們去理解繼承這個東西,理解繼承的好處,子類可以調用父類的方法,所以從而可以簡單的實現共有的一些功能,可以減少程式碼量,如果子類的計算方法和父類不一樣,還可以重寫其方法來達到目的,繼承是Java中很重要的一個內容,我們想實現一些東西,在不改變自身程式碼的情況下,我們可以給之前的程式碼加一個父類,就像老師實驗課所講的例子,如果我想給空調加一個做飯的功能而且不能對源碼做出改變,應該怎麼做,我想這時候就可以給它加一個父類來實現一些功能。
第二題也是要求我們求圖形的面積,根據圖形面積對圖形對象進行排序並輸出,第二題,這道題採用了抽象類定義,實體類構建的一個方式,我們首先有一個Shape類,但這個類與上一題不同的是,這是一個抽象類,擁有抽象的方法,求面積和數據校驗,然後它有三個子類分別是,circle類rectangle類和triangle類分別,三個類繼承於shape類,重寫了求面積和數據校驗的方法,我在主函數中分別創建三個類的對象然後將他們放入shape類型的list中,求面積的時候直接調用shape的getArea的方法就可以了,然後再根據面積對list中的對象排序,最後再輸出面積。我認為這道題主要是想讓我們更深刻的理解繼承以及去理解多態,我們求面積只需要調用shape的求面積方法,就可以直接求面積,不需要調用誰誰的求面積去求誰誰的面積,就像老師上課舉得交學費的例子,學校說交學費,只需要說一句交學費,人人就都知道自己交多少學費,學校不用去和每個學院的人說你們交多少多少學費,這就是多態的好處,繼承和多態提高了程式碼的可維護性和可延展性。
第三題還是讓我們求面積,不過第三題與第一題和第二題都不同的是第三題讓我們使用介面來實現多態,首先我們創建了一個求面積的介面,介面中有一個求面積的的方法,然後創建了倆個類一個是circle類一個是rectangle類,這兩個類都與介面相連接,這兩個類中都有求面積的方法,然後我們在主函數中創建兩個對象,聲明類型為介面,實際類型還是circle和rectangle,然後調用介面求面積的方法就可以求出面積。這道題主要的目的應該是想讓了解介面,然後用介面以及類實現多態。
三道題核心的內容其實基本都相似,都是想讓我們理解多態,通過繼承通過介面來理解多態,多態就是同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果,我們知道,封裝可以隱藏實現細節,使得程式碼模組化,繼承可以擴展已存在的程式碼模組,他們都是為了程式碼的復用,而多態除了程式碼的復用性外,還可以解決項目中緊偶合的問題,提高程式的可擴展性.。
(3)對三次題目集中用到的正則表達式技術的分析總結
三次題目集中,題目集04(7-1)題目集05(7-4),題目集06(1、2、4)都是正則表達式的練習。
正則表達式常用的知識點總結:
. 匹配除換行符以外的任意字元
\w 匹配字母或數字或下劃線
\s 匹配任意的空白符
\d 匹配數字
\b 匹配單詞的開始或結束
^ 匹配字元串的開始
$ 匹配字元串的結束
* 重複零次或更多次
+ 重複一次或更多次
? 重複零次或一次
n 重複n次
{n,} 重複n次或更多次
{n,m} 重複n到m次
\W 匹配任意不是字母,數字,下劃線,漢字的字元
\S 匹配任意不是空白符的字元
\D 匹配任意非數字的字元
\B 匹配不是單詞開頭或結束的位置
[^x] 匹配除了x以外的任意字元
[^asdf] 匹配除了asdf這幾個字母以外的任意字元
-
Pattern 類:
pattern 對象是一個正則表達式的編譯表示。Pattern 類沒有公共構造方法。要創建一個 Pattern 對象,你必須首先調用其公共靜態編譯方法,它返回一個 Pattern 對象。該方法接受一個正則表達式作為它的第一個參數。
-
Matcher 類:
Matcher 對象是對輸入字元串進行解釋和匹配操作的引擎。與Pattern 類一樣,Matcher 也沒有公共構造方法。你需要調用 Pattern 對象的 matcher 方法來獲得一個 Matcher 對象。
public boolean lookingAt()
嘗試將從區域開頭開始的輸入序列與該模式匹配。
public boolean find()
嘗試查找與該模式匹配的輸入序列的下一個子序列。
public boolean find(int start)
重置此匹配器,然後嘗試查找匹配該模式、從指定索引開始的輸入序列的下一個子序列。
public boolean matches()
嘗試將整個區域與模式匹配。
public String replaceAll(String replacement)
替換模式與給定替換字元串相匹配的輸入序列的每個子序列。
public String replaceFirst(String replacement)
替換模式與給定替換字元串匹配的輸入序列的第一個子序列。
以上是一些最常用的正則表達式的知識點。題目集04(7-1)是水文數據校驗及處理,該題讓我們使用Java中的字元串處理類以及正則表達式對輸入字元串數據進行合法性校驗及計算,主要考察的就是我們利用正則表達式去匹配和操作,然後還考察了我們對字元串的處理,題目集05(7-4)統計Java程式中關鍵詞的出現次數,該題考察點和上題考查的內容相似,但是第五題考察的非法情況以及注意事項更多一些,所以我認為難度還略大於上一題,前兩道題目比較綜合,後面的三道小題就比較簡單了,考察的都是一些基礎知識點。
總的來說,正則表達式可以使我們的程式碼簡單,我們用起來非常的方便,如果沒有正則表達式,我們可能要用for循環一個一個去判斷,所以正則表達式是幫助我們去操作字元串的一個好的工具。
(4)題目集05(7-4)中Java集合框架應用的分析總結
題目集05(7-4)統計Java程式中關鍵詞的出現次數
編寫程式統計一個輸入的Java源碼中關鍵字(區分大小寫)出現的次數。說明如下:
- Java中共有53個關鍵字(自行百度)
- 從鍵盤輸入一段源碼,統計這段源碼中出現的關鍵字的數量
- 注釋中出現的關鍵字不用統計
- 字元串中出現的關鍵字不用統計
- 統計出的關鍵字及數量按照關鍵字升序進行排序輸出
- 未輸入源碼則認為輸入非法
輸入格式:
輸入Java源碼字元串,可以一行或多行,以exit
行作為結束標誌
輸出格式:
- 當未輸入源碼時,程式輸出
Wrong Format
- 當沒有統計數據時,輸出為空
- 當有統計數據時,關鍵字按照升序排列,每行輸出一個關鍵字及數量,格式為
數量\t關鍵字
這道題讓我們匹配關鍵字,用到了正則表達式以及對字元串的操作和處理,題目還要求題目必須使用List、Set或Map中一種或多種,如完全未使用如上介面,是一道綜合性題目,由於本題難度較大,改題目並沒有完全完成。所以對該道題目的分析可能不多。
對於這道題目,剛開始看到這道題的時候感覺難度還行,有一些大致的思路,先輸入字元串,然後用正則表達式匹配,統計然後輸出,但下手的時候發現不太能下手,由於題目有很多細節的需求,以及我自己正則表達式和對字元串的應用不是很熟,所以這道題目並沒有完全做完。
3.踩坑心得
(1)第一道日期題目對於月份最大值的處理一開始用了switch和case,列舉了12個月,到最後發現了mon_maxnum這個數組都沒有用上,用case的時候不僅容易錯,而且非常複雜,在第二個程式碼中就把返回月份最大值,直接用一個簡單的方法返回了,下次做題的時候應該考慮清楚類圖中的一些屬性都有什麼用,該怎麼使用,然後再進行寫程式碼的工作,這樣可能會節省很多時間。
(2)第一道日期類的題目,在類與類之間傳輸數據的時候,數據對應錯了,在Day這個類中,我們創建了year和month的對象作為day這個類的屬性,然後寫了一個函數public Day(int yearValue,int monthValue,int dayValue),將數據傳到一起,但是寫完之後發現檢驗輸入數據是否合法的時候一直輸出wrong format,後來才發現對應的日期傳錯了,把年傳到了日,所以導致一開始總是找不到錯誤在哪裡,耽誤了很長的時間,其實跟那個類圖也有關係,跟自己也有關係,類圖那個年月日順序就錯了,也還是自己沒有特別仔細地閱讀題目。
(3)日期類的第二題和第一題有很多不同,因為年月日的類很簡單,所以在日期處理的類中,包括了一些核心演算法,而這個核心演算法的一些順序很重要,還是邏輯的問題,month.monthReduction();setDayMax();就比如這兩個程式碼的先後順序就很重要,如果按照自己的邏輯,它們兩個誰先誰後都無所謂,但是如果把這兩個程式碼位置換了的話,就會導致閏年2月到三月或者二月到1月出現問題,日期就會提前引用二月的日期,比如一月31日,但是運行後成了1月29日,就有一些邏輯錯誤,這個也改了一些時間。
(4)題目集06(7-5),圖形繼承的題,檢測輸入數據合法性,一開始不管輸入什麼數據,輸出都是wrong format,但是自己去看自己的程式碼覺得沒有問題,然後到最後最後還是發現了一些邏輯錯誤,就是檢驗輸入數據合法性,雖然都是判斷,但是先正常進行,再輸出wrong format 和先輸wrong format 也是不一樣的,所以要多注意這方面的邏輯,看看什麼樣的程式碼適合那種邏輯。
4.改進建議
(1)對於第一個日期題,我認為應該多保證類的單一性原則,所以就不應該每個類都聚合,應該把day,month,year類單獨設計出來,之間沒有關聯,就向著第二道日期題改進即可。
(2)對於題目集04第三題,繼承類題目,我認為可以寫一個操作類,然後把求面積的方法都放在這一個類中,然後讓這個類繼承這個操作類,以後還可以加求體積等方法,很方便。
5.總結
(1)首先呢,學到了一些正則表達式的知識點以及應用 還需要多加練習,更熟悉的掌握正則表達式的知識點以及用法。
(2)其次,學習到了類與類之間的關係,我認為這次最重要的就是明白了很多類與類之間的關係,比如關聯,聚合,繼承。
(3)我覺得這次的題目集,我對於繼承有了更深的理解,因為理解了繼承的好處,明白了它有什麼用處,所以更好了理解了為什麼要用繼承,繼承怎樣使用。
(4)對於類的設計,整個程式碼的設計,以及類與類之間的關係還需要進一步學習,需要通過練習來進一步掌握知識。
(5)對於老師講課的話沒有很多意見,就是希望老師可以多帶著我們寫一些程式碼,感覺這樣效果會好一些。