1.前言
第一次作业
主要涉及的知识点有基本数据类型、顺序结构、选择结构、循环结构、字符串、数组。题量很多,有12题,这对于刚学Java的我来说十分惊讶,一上来就要写这么多题,而且还是不熟悉语法的情况下,因此看到题目就有点慌了。难度的话不好说,因为大部分题目还是简单的,但第十题我感觉比较难,因为它涉及了一些String类的基本操作,而我不是很熟悉String,再加上题目理解起来可能有点难,所以我觉得第一次作业的难度还是有的。
第二次作业
主要涉及的知识点有基本数据类型、数组、顺序结构、选择结构、字符串。题量相比第一次减少了一点,一共9题。在我看来,这9题的难度适中,其中第八题和第九题的难度大一点。不知为啥比第一次作业做起来更顺畅一些,可能是在经历了第一次作业后对Java的基础语法有了更好的理解和运用,没有第一次写的那么吃力了。第二次作业考察的主要是选择结构,几乎每一题都涉及了几个选择,尤其是最后两题,很多选择结构。
第三次作业
主要涉及的知识点有构造类、LocalDate、顺序结构、选择结构,同时还要求我们能够读懂类图。题量比较少,只有四题。虽然题量少,但难度却直线上升,因为这几题都出现了构造类,这是之前没有遇到过的情形,第一次做有点不熟甚至陌生,总是要看着书本上的例题才能下手。同时,这次的第三题是第二次作业第九题的封装迭代,然后第四题又是第三题的迭代,也就是说迭代了两次,从求下一天到求下n天,前n天,以及两个日期相差的天数。第三次作业应该是为了让我们熟悉一下构造类的方法。
2.设计与分析
在这里我主要分析的是第三次作业,因为前两次作业都没有涉及到构造类。
7-1
类图
源码
1 import java.util.Scanner; 2 public class Main { 3 4 public static void main(String[] args) { 5 // TODO Auto-generated method stub 6 Circle circle=new Circle(); 7 Scanner input=new Scanner(System.in); 8 double newRadius=input.nextDouble(); 9 circle.setRadius(newRadius); 10 if(newRadius<0) 11 { 12 System.out.print("Wrong Format"); 13 return; 14 } 15 double areas=circle.getAreas(); 16 System.out.print("The circle's radius is:"); 17 System.out.println(String.format("%.2f",circle.getRadius())); 18 System.out.print("The circle's area is:"); 19 System.out.print(String.format("%.2f",circle.getAreas())); 20 } 21 22 } 23 class Circle{ 24 private double radius; 25 Circle(){ 26 radius=1; 27 } 28 double getAreas() { 29 return Math.PI*radius*radius; 30 } 31 void setRadius(double newRadius) { 32 radius=newRadius; 33 } 34 double getRadius() { 35 return radius; 36 } 37 38 }
分析
这是我第一次接触构造类,刚开始很懵,不知道怎么下手,虽然老师讲了,但是还是不太懂,然后通过看书本的例题,才知道怎么构造类,也了解了什么叫封装性,知道了private的属性不能直接调用,必须构造相应方法来给它赋值和取值。这一题比较简单,其中要注意的就是输出格式,pta上要求保留两位小数,我是采取String.format这个方法将输出格式化。
7-2
类图
源码
1 import java.util.Scanner; 2 import java.time.LocalDate; 3 public class Main { 4 public static void main(String[] args) { 5 Scanner input=new Scanner(System.in); 6 Account account=new Account(); 7 int specialId=input.nextInt(); 8 double firstBalance=input.nextDouble(); 9 double annuallnterestRate1=input.nextDouble(); 10 account.setId(specialId); 11 account.setBalance(firstBalance); 12 account.setAnnuallnterestRate(annuallnterestRate1); 13 double money1=input.nextDouble(); 14 double money2=input.nextDouble(); 15 account.withDraw(money1); 16 account.deposit(money2); 17 System.out.println("The Account'balance:"+String.format("%.2f",account.getBalance())); 18 System.out.println("The Monthly interest:"+String.format("%.2f",account.getMonthlyInterestRate())); 19 System.out.println("The Account'dateCreated:"+account.getDateCreated()); 20 21 } 22 } 23 class Account{ 24 private int id=0; 25 private double balance=0; 26 private double annuallnterestRate=0; 27 private LocalDate dateCreated=LocalDate.of(2020, 07, 31); 28 public Account(){ 29 } 30 public void Accout(int id,double balance) { 31 this.id=id; 32 this.balance=balance; 33 } 34 public void setId(int id){ 35 this.id=id; 36 } 37 public int getId() { 38 return this.id; 39 } 40 public void setBalance(double balance){ 41 this.balance=balance; 42 } 43 public double getBalance() { 44 return this.balance; 45 } 46 public void setAnnuallnterestRate(double annuallnterestRate){ 47 this.annuallnterestRate=annuallnterestRate; 48 } 49 public double getAnnuallnterestRate() { 50 return this.annuallnterestRate; 51 } 52 public LocalDate getDateCreated() { 53 return this.dateCreated; 54 } 55 public double getMonthlyInterestRate() { 56 return this.balance*(this.annuallnterestRate/1200); 57 } 58 public void withDraw(double money){ 59 if(money>this.balance||money<0) 60 { 61 System.out.println("WithDraw Amount Wrong"); 62 } 63 else 64 { 65 this.balance=this.balance-money; 66 } 67 } 68 public void deposit(double money) { 69 if(money>20000||money<0) 70 { 71 System.out.println("Deposit Amount Wrong"); 72 } 73 else 74 { 75 this.balance=this.balance+money; 76 } 77 } 78 79 }
分析
这题并不难,在做过第一题之后,更清楚了类的操作,所以只要知道各个数值是怎么计算得来的差不多就能写出来,要注意的就是输出格式的问题。对了,这题还需要稍微了解一下LocalDate这个类,它可以方便的对日期进行相关操作。
7-3
类图
源码
1 import java.util.Scanner; 2 public class Main { 3 public static void main(String[] args) { 4 Scanner input=new Scanner(System.in); 5 int year=input.nextInt(); 6 int month=input.nextInt(); 7 int day=input.nextInt(); 8 Date date=new Date(year,month,day); 9 date.getNextDate(); 10 } 11 } 12 class Date{ 13 private int year=1900; 14 private int month=1; 15 private int day=1; 16 protected int[]mon_maxnum=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31}; 17 public Date(){} 18 public Date(int year,int month,int day) { 19 this.year=year; 20 this.month=month; 21 this.day=day; 22 } 23 public int getYear() { 24 return this.year; 25 } 26 public void setYear(int year) { 27 this.year=year; 28 } 29 public int getMonth() { 30 return this.month; 31 } 32 public void setMonth(int month) { 33 this.month=month; 34 } 35 public int getDay() { 36 return this.day; 37 } 38 public void setDay(int day) { 39 this.day=day; 40 } 41 public boolean isleapYear(int year) { 42 if(year%400==0||(year%4==0&&year%100!=0)) 43 { 44 return true; 45 } 46 else 47 { 48 return false; 49 } 50 } 51 public boolean checkInputValidity() { 52 if(isleapYear(this.year)) 53 { 54 this.mon_maxnum[2]=29; 55 } 56 else 57 { 58 this.mon_maxnum[2]=28; 59 } 60 if(this.year<1900||this.year>2000) 61 { 62 return false; 63 } 64 else if(this.month<1||this.month>12){ 65 return false; 66 } 67 else if(this.day>this.mon_maxnum[this.month]||this.day<1){ 68 return false; 69 } 70 else 71 { 72 return true; 73 } 74 } 75 public void getNextDate() { 76 if(isleapYear(this.year)) 77 { 78 this.mon_maxnum[2]=29; 79 } 80 else 81 { 82 this.mon_maxnum[2]=28; 83 } 84 if(checkInputValidity()==false) 85 { 86 System.out.print("Date Format is Wrong"); 87 System.exit(0); 88 } 89 else 90 { 91 if(this.day<this.mon_maxnum[this.month]) 92 { 93 this.day++; 94 } 95 else if(this.month!=12&&this.day==this.mon_maxnum[this.month]) 96 { 97 this.day=1; 98 this.month++; 99 } 100 else if(this.month==12&&this.day==31) 101 { 102 this.day=1; 103 this.month=1; 104 this.year++; 105 } 106 System.out.print("Next day is:"+this.year+"-"+this.month+"-"+this.day); 107 return; 108 } 109 } 110 }
分析
当老师在课堂上说让我们写一个程序求下一天的时候,我就觉得这个题目不简单,因为要考虑蛮多因素,比如输入日期是否合法,年份是否为闰年,当天是否为该月最后一天,又或者下一天是否直接是下一年的第一天了。说一下判断闰年的方法,如果输入的年份能被400整除或者能被4整除但不能被100整除,那么该年为闰年。然后我说一下自己求下一天的思路:先判断年份是否为闰年,如果是,那么2月天数就为29天,此时月份数组mon_maxnum[2] = 29;然后判断这一天是否为该月最后一天,如果不是,则直接天数+1,如果是的话,再判断该月是否为12月,如果不是,天数改为1,月份+1,如果是的话,天数和月份均改为1,并且将年份+1。
7-4
类图
源码
1 import java.util.Scanner; 2 public class Main { 3 public static void main(String[] args) { 4 Scanner input = new Scanner(System.in); 5 int year = 0; 6 int month = 0; 7 int day = 0; 8 9 int choice = input.nextInt(); 10 11 if (choice == 1) { // test getNextNDays method 12 int m = 0; 13 year = Integer.parseInt(input.next()); 14 month = Integer.parseInt(input.next()); 15 day = Integer.parseInt(input.next()); 16 17 DateUtil date = new DateUtil(year, month, day); 18 19 if (!date.checkInputValidity()) { 20 System.out.println("Wrong Format"); 21 System.exit(0); 22 } 23 24 m = input.nextInt(); 25 26 if (m < 0) { 27 System.out.println("Wrong Format"); 28 System.exit(0); 29 } 30 31 System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:"); 32 System.out.println(date.getNextNDays(m).showDate()); 33 } else if (choice == 2) { // test getPreviousNDays method 34 int n = 0; 35 year = Integer.parseInt(input.next()); 36 month = Integer.parseInt(input.next()); 37 day = Integer.parseInt(input.next()); 38 39 DateUtil date = new DateUtil(year, month, day); 40 41 if (!date.checkInputValidity()) { 42 System.out.println("Wrong Format"); 43 System.exit(0); 44 } 45 46 n = input.nextInt(); 47 48 if (n < 0) { 49 System.out.println("Wrong Format"); 50 System.exit(0); 51 } 52 53 System.out.print( 54 date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:"); 55 System.out.println(date.getPreviousNDays(n).showDate()); 56 } else if (choice == 3) { //test getDaysofDates method 57 year = Integer.parseInt(input.next()); 58 month = Integer.parseInt(input.next()); 59 day = Integer.parseInt(input.next()); 60 61 int anotherYear = Integer.parseInt(input.next()); 62 int anotherMonth = Integer.parseInt(input.next()); 63 int anotherDay = Integer.parseInt(input.next()); 64 65 DateUtil fromDate = new DateUtil(year, month, day); 66 DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay); 67 68 if (fromDate.checkInputValidity() && toDate.checkInputValidity()) { 69 System.out.println("The days between " + fromDate.showDate() + 70 " and " + toDate.showDate() + " are:" 71 + fromDate.getDaysofDates(toDate)); 72 } else { 73 System.out.println("Wrong Format"); 74 System.exit(0); 75 } 76 } 77 else{ 78 System.out.println("Wrong Format"); 79 System.exit(0); 80 } 81 } 82 } 83 class DateUtil{ 84 private int year=1820; 85 private int month=1; 86 private int day=1; 87 protected int[]mon_maxnum=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31}; 88 public DateUtil(){} 89 public DateUtil(int year,int month,int day) { 90 this.year=year; 91 this.month=month; 92 this.day=day; 93 } 94 public int getYear() { 95 return this.year; 96 } 97 public void setYear(int year) { 98 this.year=year; 99 } 100 public int getMonth() { 101 return this.month; 102 } 103 public void setMonth(int month) { 104 this.month=month; 105 } 106 public int getDay() { 107 return this.day; 108 } 109 public void setDay(int day) { 110 this.day=day; 111 } 112 public boolean isLeapYear(int year) { 113 if(year%400==0||(year%4==0&&year%100!=0)) 114 { 115 return true; 116 } 117 else 118 { 119 return false; 120 } 121 } 122 public boolean checkInputValidity(){ 123 if(isLeapYear(this.year)) 124 { 125 this.mon_maxnum[2]=29; 126 } 127 else 128 { 129 this.mon_maxnum[2]=28; 130 } 131 if(this.year<1820||this.year>2020||this.day>this.mon_maxnum[this.month]||this.day<1||this.month<1||this.month>12) 132 { 133 return false; 134 } 135 else 136 { 137 return true; 138 } 139 } 140 public DateUtil getNextNDays(int n) { 141 while(n>365) { 142 143 if(isLeapYear(this.year)&&this.month<=2) { 144 if(this.month==2&&this.day==29) { 145 this.day=1; 146 this.month=3; 147 } 148 this.year++; 149 n-=366; 150 } 151 else if(isLeapYear(this.year+1)&&this.month>2) { 152 this.year++; 153 n-=366; 154 } 155 else { 156 this.year++; 157 n-=365; 158 } 159 } 160 for(int i=0;i<n;i++) { 161 if(isLeapYear(this.year)){ 162 this.mon_maxnum[2]=29; 163 } 164 else { 165 this.mon_maxnum[2]=28; 166 } 167 if(this.day<this.mon_maxnum[this.month]) { 168 this.day++; 169 } 170 else if(this.month!=12&&this.day==this.mon_maxnum[this.month]){ 171 this.day=1; 172 this.month++; 173 } 174 else if(this.month==12&&this.day==31){ 175 this.day=1; 176 this.month=1; 177 this.year++; 178 } 179 180 } 181 return this; 182 } 183 public DateUtil getPreviousNDays(int n) { 184 if(n==0){ 185 return this; 186 } 187 188 189 while(n>365){ 190 if(isLeapYear(this.year)&&this.month>2) { 191 this.year--; 192 n-=366; 193 } 194 else if(isLeapYear(this.year-1)&&this.month<=2) { 195 this.year--; 196 n-=366; 197 } 198 else { 199 this.year--; 200 n-=365; 201 } 202 } 203 for(int i=0;i<n;i++) { 204 if(isLeapYear(this.year)){ 205 this.mon_maxnum[2]=29; 206 } 207 else { 208 this.mon_maxnum[2]=28; 209 } 210 if(this.day>1) { 211 this.day--; 212 } 213 else if(this.day==1) { 214 this.day=this.mon_maxnum[this.month-1]; 215 if(month!=1) { 216 this.month--; 217 } 218 if(this.month==1) { 219 this.year--; 220 this.month=12; 221 } 222 } 223 } 224 this.month++; 225 return this; 226 } 227 public boolean compareDates(DateUtil date) { 228 if(this.year>date.year) 229 { 230 return true; 231 } 232 else if(this.year==date.year&&this.month>date.month) 233 { 234 return true; 235 } 236 else if(this.year==date.year&&this.month==date.month&&this.day>date.day) 237 { 238 return true; 239 } 240 else 241 { 242 return false; 243 } 244 245 } 246 public boolean equalTwoDates(DateUtil date) { 247 if(this.year==date.year&&this.month==date.month&&this.day==date.day) 248 { 249 return true; 250 } 251 else 252 { 253 return false; 254 } 255 } 256 public int getDaysofDates(DateUtil date) { 257 258 int daysBetween=0; 259 int[]mon_maxnum=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31}; 260 int yearSum=0; 261 int monthSum1=0; 262 int monthSum2=0; 263 int t; 264 265 if(year>date.year) { 266 t=date.year; 267 date.year=year; 268 year=t; 269 } 270 for(int i=year;i<date.year;i++) { 271 if(isLeapYear(i)) { 272 yearSum+=366; 273 } 274 else { 275 yearSum+=365; 276 } 277 } 278 for(int i=1;i<month;i++) { 279 monthSum1+=mon_maxnum[i]; 280 } 281 if(isLeapYear(year)&&month>2) { 282 monthSum1++; 283 } 284 for(int i=1;i<date.month;i++) { 285 monthSum2+=mon_maxnum[i]; 286 } 287 if(isLeapYear(date.year)&&date.month>2) { 288 monthSum2++; 289 } 290 291 daysBetween=yearSum+monthSum2+date.day-monthSum1-day; 292 return daysBetween; 293 294 } 295 public String showDate() { 296 return String.format("%d-%d-%d", year,month,day); 297 } 298 }
分析
这一题是7-3的迭代,它在7-3的基础上进行升级,同时还要求前n天和两个日期相差的天数,算法应该是目前为止遇到的最复杂的了。先说一下求下n天的方法:如果n大于365,则进行第一个for循环将n减到小于等于364天,在循环里,如果该年为闰年并且月份小于等于2月,然后日期又为2月29日,则下一年后的这天为3月1日,否则月份和天数不变,n-366;如果该年的下一年为闰年并且月份大于2月,则下一年后的这天日期不变,n-366;如果上面情况都不符合,则下一年后的这天日期不变,n-365。再用第二个for循环用7-3的方法循环n次,得到剩余n天后的日期即为一开始要求的第n天后的日期。求前n天的方法与求下n天的方法类似,但判断的情况有一些不同,只要把判断的点想清楚就能写出来,这里就不阐述了。然后说一下求两个日期相差的天数的方法:我是分年,月,日来算的,先算相差的年份的总天数,求完后相当于这两个日期都在同一年了,再求相差的月份的总天数,最后再求两个日期中day相差的天数,最后把这三个相差的天数相加得到总天数。
3.踩坑心得
第一次作业
在作业一踩的最粗心的坑就是pta上的编译器没有选择Java,用了好多次c语言编译器进行编译,结果编译错误了好久,让我一度以为是自己代码有语法错误,直到第二天看到老师在群里的提醒,我才发现要用Java编译器,一下醒悟过来,现在想一想我当初真的太粗心马虎了。除了这个,就是输出结果的格式问题导致我经常部分正确,然后改完输出格式后就正确了,所以这告诉我在以后的做题中要仔细地考虑输出结果格式,不要因为这个而丢了分。
踩坑截图
改正后
在换了编译器后,我是部分正确,在经过几次改进后才艰辛的得到正确答案。第一次写Java就感觉到了与c语言的不同之处。
第二次作业
在作业二中踩的印象最深的坑就是7-8中的等腰直角三角形的判断情况,因为这里涉及浮点数判等。这个判断卡了我好长一段时间,一直过不了这个测试点。最后在老师的提示以及询问了班上的大佬之后,才知道浮点数判等必须两个浮点数的差的绝对值在一个很小很小的范围内才能判等。除了这个坑外,在写7-9的时候,我没有用月份数组来储存每个月份的天数,而是一个一个月份列举,使得代码十分冗长,这个在第三次作业上的7-3和7-4都进行了改进。
踩坑截图
改正后
第三次作业
似乎没有踩到什么坑,但是算法上思考了很久,同时询问了好几个同学,因为前面已经分析过第三次作业了,这里就不再阐述了。详情请见“设计与分析”。
4.改进建议
(1)刚接触Java,不知道相应的代码规范,虽然老师发了阿里的代码规范,但是我没有很重视,所以在前三次作业中的代码都很不规范,在以后的Java学习中我会遵守相应的代码规范,不再随意写代码。
(2)题目中有的方法不够方便,比较繁琐。就比如第二次作业中的7-9求下一天,我将月份一个一个列举出来判断,导致判断很冗长。因此我以后得多多向优秀的同学学习,多与他们讨论代码,看一下自己的代码存在哪些不足的地方然后加以改进。
(3)写题目时要注意输出结果的格式问题,比如保留两位小数之类的
(4)写题目时要认真考虑边界值。
5.总结
获得的知识
通过这三次作业,我熟悉了Java的一些基础语法,同时也知道了构造类的方法,充分意识到Java与C语言的不同,了解了Java的封装性,进一步明白它面向对象程序设计的独特性。同时我还学习了一些类的使用方法,比如LocalDate,Random类。
需要进一步学习的知识
我觉得我需要系统地学习Java知识,不能老是遇到问题就去查零散的知识,要多看书本和询问同学,书本是获取知识的最好途径,《Java语言程序设计》这本书有很完整的Java知识,希望在以后能先从书本里学到系统的知识再去做题。这个专业很难,需要我们长期的努力学习。我们必须循序渐进,一步一个脚印,踏实写好每一次作业和实验。