java第4-6次作业总结
一.前言:
我认为这三次的题目整体难度适中,与类有关的设计题目都有提示。主要的知识点当然是面向对象的六个字:封装、继承、多态。并且再次加深学习了正则表达式(好用确实好用)。
我对封装、继承、多态的理解:1、封装是隐藏对象的属性和实现细节,对外提供公共的访问方式,以防止数据的随意访问和修改;2、继承是通过扩展一个已有的类,并继承该类的属性和行为,来创建一个新的类;3、接口的多种不同的实现方式即为多态。
二.设计与分析:
①题目集4(7-2)、题目集5(7-4)两种日期类聚合设计的优劣比较
这两个题目基本是一样的,不过题目是两种不同的类设计,如下图:
题目集4(7-2)的类图设计

题目集5(7-4)的类图设计

做题的时候本人没有注意,都是使用的第一种类设计过的题目。以下给出相关代码以及所实现的类图:
代码如下:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); switch(in.nextInt()) { case 1: DateUtil date = new DateUtil(in.nextInt(), in.nextInt(), in.nextInt()); if(date.checkInputValidity()) { date.getNextNDays(in.nextInt()); System.out.println(date.showDate()); } else { System.out.println("Wrong Format"); } break; case 2: date = new DateUtil(in.nextInt(), in.nextInt(), in.nextInt()); if(date.checkInputValidity()) { date.getPreviousNDays(in.nextInt()); System.out.println(date.showDate()); } else { System.out.println("Wrong Format"); } break; case 3: DateUtil date1 = new DateUtil(in.nextInt(), in.nextInt(), in.nextInt()); DateUtil date2 = new DateUtil(in.nextInt(), in.nextInt(), in.nextInt()); if(date1.checkInputValidity()&&date2.checkInputValidity()) { System.out.println(date1.getDaysofDates(date2)); } else { System.out.println("Wrong Format"); } break; default:System.out.println("Wrong Format"); } in.close(); } } class DateUtil{ private Day day = new Day(); DateUtil(){ } DateUtil(int y, int m, int d){ this.day.setDayValue(d); this.day.getMonth().setMonthValue(m); this.day.getMonth().getYear().setyearValue(y); } Day getDay() { return day; } void setDay(Day day) { this.day = day; } boolean checkInputValidity() {//校验数据的合法性 if(this.day.getMonth().getYear().validate()&&this.day.getMonth().validate()&&this.day.validate()) { return true; } else { return false; } } boolean compareDates(DateUtil date) {//比较两个日期的大小,比date大返回true if(this.day.getMonth().getYear().getyearValue()>date.day.getMonth().getYear().getyearValue()) { return true; } else if(this.day.getMonth().getYear().getyearValue()<date.day.getMonth().getYear().getyearValue()){ return false; } else { if(this.day.getMonth().getMonthValue()>date.day.getMonth().getMonthValue()) { return true; } else if(this.day.getMonth().getMonthValue()<date.day.getMonth().getMonthValue()) { return false; } else { if(this.day.getDayValue()>date.day.getDayValue()) { return true; } else if(this.day.getDayValue()<date.day.getDayValue()) { return false; } else {//日期相等 return false; } } } } boolean equalTwoDates(DateUtil date) {//判断两个日期是否相等 if(this.day.getDayValue()==date.day.getDayValue()) { if(this.day.getMonth().getMonthValue()==date.day.getMonth().getMonthValue()) { if(this.day.getMonth().getYear().getyearValue()==date.day.getMonth().getYear().getyearValue()) { return true; } } } return false; } String showDate() {//日期值格式化 return String.valueOf(this.day.getMonth().getYear().getyearValue())+"-"+String.valueOf(this.day.getMonth().getMonthValue())+"-"+String.valueOf(this.day.getDayValue()); } DateUtil getNextNDays(int n) {//求下n天 for(int i = 0; i < n; i++) { this.day.dayIncrement(); if(!this.day.validate()) { this.day.getMonth().monthIncrement(); if(!this.day.getMonth().validate()) { this.day.getMonth().getYear().yearIncrement(); this.day.getMonth().resetMin(); } this.day.resetMin(); } } return this; } DateUtil getPreviousNDays(int n) {//求前n天 for(int i = 0; i < n; i++) { this.day.dayReduction(); if(!this.day.validate()) { this.day.getMonth().monthReduction(); if(!this.day.getMonth().validate()) { this.day.getMonth().getYear().yearReduction(); this.day.getMonth().resetMax(); } this.day.resetMax(); } } return this; } int getDaysofDates(DateUtil date) {//求两个日期之间的天数 int sum = 0; while(!this.equalTwoDates(date)) { sum++; if(this.compareDates(date)) { date.getNextNDays(1); } else { date.getPreviousNDays(1); } } return sum; } } class Year{ private int yearValue; Year(){ } Year(int yearValue){ this.yearValue = yearValue; } int getyearValue() { return yearValue; } void setyearValue(int yearValue) { this.yearValue = yearValue; } boolean isLeapYear() {//判断是否为闰年 if((this.yearValue%4==0&&this.yearValue%100!=0)||this.yearValue%400==0) { return true; } else { return false; } } boolean validate() {//校验数据合法性 if(this.yearValue>=1900&&this.yearValue<=2050) { return true; } else { return false; } } void yearIncrement() {//年份增一 this.yearValue++; } void yearReduction() {//年份减一 this.yearValue--; } } class Month{ private int monthValue; private Year year = new Year(); Month(){ } Month(int yearValue, int monthValue){ this.monthValue = monthValue; this.year.setyearValue(yearValue); } int getMonthValue() { return monthValue; } void setMonthValue(int monthValue) { this.monthValue = monthValue; } Year getYear() { return year; } void setYear(Year year) { this.year = year; } void resetMin() {//月份复位(1) this.monthValue = 1; } void resetMax() {//月份设置为12 this.monthValue = 12; } boolean validate() {//校验数据合法性 if(this.monthValue>=1&&this.monthValue<=12) { return true; } else { return false; } } void monthIncrement() {//月份增一 this.monthValue++; } void monthReduction() {//月份减一 this.monthValue--; } } class Day{ private int dayValue; private Month month = new Month(); private int[] mon_maxnum = new int[] {31,28,31,30,31,30,31,31,30,31,30,31}; Day(){ } Day(int yearValue, int monthValue, int dayValue){ this.dayValue = dayValue; this.month.setMonthValue(monthValue); this.month.getYear().setyearValue(yearValue);; } int getDayValue() { return dayValue; } void setDayValue(int dayValue) { this.dayValue = dayValue; } Month getMonth() { return month; } void setMonth(Month month) { this.month = month; } void resetMin() {//日期复位(1) this.dayValue = 1; } void resetMax() {//日期设为该月最大值 if(this.month.getYear().isLeapYear()) { this.mon_maxnum[1] = 29; } this.dayValue = this.mon_maxnum[this.month.getMonthValue()-1]; } boolean validate() {//校验数据的合法性 if(this.month.getYear().isLeapYear()) { this.mon_maxnum[1] = 29; } else { this.mon_maxnum[1] = 28; } if(this.dayValue>=1&&this.dayValue<=this.mon_maxnum[this.month.getMonthValue()-1]) { return true; } else { return false; } } void dayIncrement() {//日期增一 this.dayValue++; } void dayReduction() {//日期减一 this.dayValue--; } }
类图以及分析图如下:


写的不是很好圈复杂度还是超了点。
这题写的方法用在另一题开始在数据最大点没有过,多次调试发现将for循环改为while循环即可通过(奇怪的知识又增加了,java中while循环比for快多了)



由于没有用第二种类设计写,在这里脑测一下:我感觉我比较喜欢第二种的类设计,第一种给我的感觉就是无限套娃,在需要用到更深的类方法要写出很长一句,不方便阅读等。第一种线性,层次清晰,第二种实用方便。
②题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)
这三题主要是类的继承和多态性,以及接口的运用。题目集6(7-6)用了一个接口,无属性,只有一个GetArea(求面积)的抽象方法,题目集4(7-3)中Ball继承Circle,Box继承Rectangle,而Circle与Rectangle都是继承Shape类。
题目集4(7-3)的源码以及类图如下:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); /* * 1 圆半径 2 矩形宽、长 3 球半径 4 立方体宽、长、高 */ switch(in.nextInt()) { case 1:double radius = in.nextDouble(); if(radius>0) { Circle cir = new Circle(radius); System.out.printf("Circle's area:%.2f\n", cir.getArea()); } else { System.out.println("Wrong Format"); } break; case 2:double width = in.nextDouble(), length = in.nextDouble(); if(width>0&&length>0) { Rectangle rec = new Rectangle(width, length); System.out.printf("Rectangle's area:%.2f\n", rec.getArea()); } else { System.out.println("Wrong Format"); } break; case 3:radius = in.nextDouble(); if(radius>0) { Ball bal = new Ball(radius); System.out.printf("Ball's surface area:%.2f\n", bal.getArea()); System.out.printf("Ball's volume:%.2f\n", bal.getVolume()); } else { System.out.println("Wrong Format"); } break; case 4:width = in.nextDouble(); length = in.nextDouble();double height = in.nextDouble(); if(width>0&&length>0&&height>0) { Box box = new Box(width, length, height); System.out.printf("Box's surface area:%.2f\n", box.getArea()); System.out.printf("Box's volume:%.2f\n", box.getVolume()); } else { System.out.println("Wrong Format"); } break; default:System.out.println("Wrong Format"); } in.close(); } } class Shape{ Shape(){ System.out.println("Constructing Shape"); } public double getArea() {//求图形面积 return 0.0; } } class Circle extends Shape{ private double radius; Circle(double radius){ this.radius = radius; System.out.println("Constructing Circle"); } public double getArea() {//求圆的面积 return this.radius*this.radius*Math.PI; } double getRadius() { return radius; } void setRadius(double radius) { this.radius = radius; } } class Rectangle extends Shape{ private double width; private double length; Rectangle(double width, double length){ this.width = width; this.length = length; System.out.println("Constructing Rectangle"); } public double getArea() {//求矩形面积 return this.length*this.width; } double getWidth() { return width; } void setWidth(double width) { this.width = width; } double getLength() { return length; } void setLength(double length) { this.length = length; } } class Ball extends Circle{ Ball(double radius){ super(radius); System.out.println("Constructing Ball"); } public double getArea() {//求球的面积 return 4*Math.PI*super.getRadius()*super.getRadius(); } public double getVolume(){//求球体积 return 4*Math.PI*Math.pow(super.getRadius(), 3)/3; } } class Box extends Rectangle{ private double height; Box(double width, double length, double height){ super(width, length); this.height = height; System.out.println("Constructing Box"); } public double getArea() {//求矩形面积 return super.getLength()*super.getWidth()*2+this.height*super.getWidth()*2+super.getLength()*this.height*2; } public double getVolume(){//求立方体体积 return this.height*super.getWidth()*super.getLength(); } double getHeight() { return height; } void setHeight(double height) { this.height = height; } }


题目集6(7-5)的源码以及类图如下:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner in = new Scanner(System.in); ArrayList<Shape> list = new ArrayList<>(); int a, b, c; a = in.nextInt(); b = in.nextInt(); c = in.nextInt(); for(int i = 0; i < a; i++) { Circle circle = new Circle(in.nextDouble()); list.add(circle); } for(int i = 0; i < b; i++) { Rectangle rectangle = new Rectangle(in.nextDouble(), in.nextDouble()); list.add(rectangle); } for(int i = 0; i < c; i++) { Triangle triangle = new Triangle(in.nextDouble(), in.nextDouble(), in.nextDouble()); list.add(triangle); } if(a==0&&b==0&&c==0) { Data.show(list); } else if(!Data.validate(list)) { System.out.println("Wrong Format"); } else { Data.show(list); } in.close(); } } /* * 数据处理类 */ class Data{ static boolean validate(ArrayList<Shape> list) {//合法性校验 if(list.size()==0) return false; for(int i = 0; i < list.size(); i++) { if(!list.get(i).validate()) return false; } return true; } static void shapeSort(ArrayList<Shape> list) {//图形排序 Collections.sort(list, new Comparator<Shape>(){ @Override public int compare(Shape o1, Shape o2) { // TODO 自动生成的方法存根 if(o1.getArea()-o2.getArea()>0) return 1; else return -1; } }); } static double getAllArea(ArrayList<Shape> list) {//面积求和 double sum = 0; for(int i = 0; i < list.size(); i++) { sum += list.get(i).getArea(); } return sum; } static void show(ArrayList<Shape> list) {//输出面积 System.out.println("Original area:"); for(int i = 0; i < list.size(); i++) { System.out.printf("%.2f ", list.get(i).getArea()); } System.out.printf("\nSum of area:%.2f\n", getAllArea(list)); System.out.println("Sorted area:"); shapeSort(list); for(int i = 0; i < list.size(); i++) { System.out.printf("%.2f ", list.get(i).getArea()); } System.out.printf("\nSum of area:%.2f", getAllArea(list)); } } /* * 图形类 */ class Shape{ Shape(){ } double getArea() {//图形面积 return 0; } boolean validate() {//合法性校验 return true; } public String toString() { return getClass().getName(); } } /* * 圆形类,继承图形类 */ class Circle extends Shape{ private double radius; Circle(double radius){ this.radius = radius; } boolean validate() {//合法性校验 if(this.radius>0) return true; else return false; } double getArea() {//图形面积 return Math.PI*this.radius*this.radius; } } /* * 矩形类,继承图形类 */ class Rectangle extends Shape{ private double width; private double length; Rectangle(double width, double length){ this.length = length; this.width = width; } boolean validate() {//合法性校验 if(this.length>0&&this.width>0) return true; else return false; } double getArea() {//图形面积 return this.length*this.width; } } /* * 三角形类,继承图形类 */ class Triangle extends Shape{ private double side1; private double side2; private double side3; Triangle(double side1, double side2, double side3){ this.side1 = side1; this.side2 = side2; this.side3 = side3; } boolean validate() {//合法性校验 if(this.side1>0&&this.side2>0&&this.side3>0) { if(this.side1+this.side2>this.side3 && this.side2+this.side3>this.side1 && this.side1+this.side3>this.side2) return true; else return false; } else return false; } double getArea() {//图形面积 double l = (this.side1+this.side2+this.side3)/2; return Math.sqrt(l*(l-this.side1)*(l-this.side2)*(l-this.side3)); } }


题目集6(7-6)的源码以及类图如下:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner in = new Scanner(System.in); Circle circle = new Circle(in.nextDouble()); Rectangle rectangle = new Rectangle(in.nextDouble(), in.nextDouble()); if(circle.validate()&&rectangle.validate()) { System.out.printf("%.2f\n", circle.getArea()); System.out.printf("%.2f\n", rectangle.getArea()); } else { System.out.println("Wrong Format"); } in.close(); } } /* * 求图形的面积接口 */ interface GetArea{ double getArea(); } /* * 圆形类,实现GetArea接口 */ class Circle implements GetArea{ private double radius; Circle(){ } Circle(double radius){ this.radius = radius; } double getRadius() { return radius; } void setRadius(double radius) { this.radius = radius; } boolean validate() {//合法性校验 if(this.radius>0) return true; else return false; } public double getArea() {//图形面积 return Math.PI*this.radius*this.radius; } } /* * 矩形类,实现GetArea接口 */ class Rectangle implements GetArea{ private double width; private double length; Rectangle(){ } Rectangle(double width, double length){ this.length = length; this.width = width; } double getWidth() { return width; } void setWidth(double width) { this.width = width; } double getLength() { return length; } void setLength(double length) { this.length = length; } boolean validate() {//合法性校验 if(this.length>0&&this.width>0) return true; else return false; } public double getArea() {//图形面积 return this.length*this.width; } }


③对三次题目集中用到的正则表达式技术的分析总结
几次实验下来,正则表达式是个非常好用的东西,本次又学会了正则表达式的贪婪以及非贪婪匹配,单词边界\b。
④题目集5(7-4)中Java集合框架应用的分析总结
题目集5(7-4)统计Java程序中关键词的出现次数

我的思路:设计一个关键字类保存其字符串以及出现次数,一个总关键字类记录所有的关键字。
在去除注释的代码时需要注意,正则匹配的时候使用非贪婪匹配。
(另外,第二个测试点有问题(大佬告诉我的),我是强行过点的)
源码以及类图如下:
import java.util.Arrays; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main{ public static void main(String[] args) { Scanner in = new Scanner(System.in); Source source = new Source(); String s; while(!(s=in.nextLine()).equals("exit")) { source.setAddSb(s+"\n"); } source.getResult(); //System.out.println(source.setNewSource()); in.close(); } } /* * 记录输入的源码 */ class Source{ StringBuilder sb = new StringBuilder(); StringBuilder getSb() { return sb; } void setSb(StringBuilder sb) { this.sb = sb; } void setAddSb(String sb) { this.sb.append(sb); } //返回去掉不需要匹配的源码字符串 String setNewSource() { String s = this.sb.toString().replaceAll("//.*", ""); s = s.replaceAll("/\\*(.*?\\s)*?\\*/", " "); s = s.replaceAll("\"(.*?)\"", " "); return s; } void getResult() { AllKey allkey = new AllKey(); String s = this.setNewSource(); if(s.isEmpty()) { System.out.println("Wrong Format"); } else { for(int i = 0; i < allkey.getNum(); i++) { // \\b单词边界 Pattern p = Pattern.compile(("\\b"+allkey.getKey()[i].getStr()+"\\b")); Matcher m = p.matcher(s); while(m.find()) { allkey.getKey()[i].sumAdd(); } } allkey.show(); } } } /* * 每个关键字的字符串以及次数统计 */ class Key{ private int sum = 0;//关键字出现次数 private String str = new String(); Key(){ } Key(String str){ this.str = str; } int getSum() { return sum; } void setSum(int sum) { this.sum = sum; } String getStr() { return str; } void setStr(String str) { this.str = str; } void sumAdd() { this.sum++; } } /* * 所有的关键字 */ class AllKey{ private String[] keystr = new String[] {"abstract","assert","boolean","break","byte", "case","catch","char","class","continue","default","do","double","else","enum", "extends","final","finally","float","for","if","implements","import","int","interface", "instanceof","long","native","new","package","private","protected","public","return", "short","static","strictfp","super","switch","synchronized","this","throw","throws", "transient","try","void","volatile","while","goto","const","true","false","null"}; private int num = keystr.length;//关键词数目 private Key[] key = new Key[num]; AllKey() { Arrays.sort(keystr); for(int i = 0; i < num; i++) { key[i] = new Key(keystr[i]); } } String[] getKeystr() { return keystr; } int getNum() { return num; } Key[] getKey() { return key; } void show() { for(Key i:key) { if(i.getSum()>0) if(i.getStr().equals("null")&&i.getSum()==1){ boolean flag = true; for(Key j:key) { if(j.getSum()==0) flag = false; } if(flag) System.out.println(i.getSum()+"\t"+i.getStr()); } else System.out.println(i.getSum()+"\t"+i.getStr()); } } }


三.采坑心得:
题目集5(7-4)统计Java程序中关键词的出现次数这题开始没有学会使用非贪婪匹配,在去除注释的时候debug了好久。
题目集5(7-4)日期问题中前n天与后n天的最大数据测试的时候超时了,结果发现将for循环改用while循环就能过了(测试下来时间差距还是挺大的)。
四.改进建议:
题目集6的7-1到7-4这四个正则表达式子的匹配,我认为融合为一个题目较好,设计相应的类。
五.总结:
本次学到了挺多的东西,正则表达式的熟练运用, 有关类的设计实现。与本人上次相比较,发现自己还是有所进步的,圈复杂度等都还行。
我对封装、继承、多态有了更深的理解,1、封装是隐藏对象的属性和实现细节,对外提供公共的访问方式,以防止数据的随意访问和修改;2、继承是通过扩展一个已有的类,并继承该类的属性和行为,来创建一个新的类;3、接口的多种不同的实现方式即为多态。

浙公网安备 33010602011771号