题目集4~6总结

(1)前言:

题目集04:主要考查了类和对象间的联系,如何将不同类间相联系,实例化,继承,父类与子类的关系和基本概念。其中题目7-1难度较大,需对正则表达式由较高的掌握,7-2难度适中,7-3较简单,是继承的基础问题。

题目集05:题目7-1~7-3主要考察的知识点是对数组的运用,对数组的分割,排序,组合等功能的实现;题目7-4难度大,考察的是java集合框架;题目7-5是题目集04 7-2的第二个版本,其类图与之前不同,主要区别在于在不同的类中创建对象。

题目集06:题目量大但难度低,多为较基础的题目:正则表达式的基本运用、继承、多态和接口的运用。

(2)设计与分析:

题目集04 7-2 日期问题面向对象设计(聚合一) (35 分)

参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:

 

 

 

 

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

  1. 求下n
  2. 求前n
  3. 求两个日期相差的天数

注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)

输入格式:

有三种输入方式(以输入的第一个数字划分[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且输入均有效,输出格式如下:
  • 天数值

提交源码:

import java.util.Scanner;

 

class Date {

    private int year;

    private int month;

    private int day;

 

    public Date(int year, int month, int day) {

        this.year = year;

        this.month = month;

        this.day = day;

    }

 

 

    public int getDay() {

        return day;

    }

 

    public int getMonth() {

        return month;

    }

 

    public int getYear() {

        return year;

    }

 

    public static boolean isLeapYear(int year) {//判断year是否为闰年,返回boolean类型;

        boolean isLeapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;

        return isLeapYear;

    }

 

    int[] DayOfMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

 

    public int getDaysOfMonth(int year, int month) {

        int days;

        days = DayOfMonth[month - 1];

        if (isLeapYear(year) && month == 2) {

            days = 29;

        }

        return days;

    }

 

    public boolean checkInputValidity()//判断输入日期是否合法,返回布尔值

    {

        boolean checkInputValidity = (year >= 1900 && year <= 2050) && (month <= 12 && month >= 1) && (day > 0 && day <= getDaysOfMonth(year,month));

        return checkInputValidity;

    }

 

    public Date getNNextDays(int n) {

        int year = this.year;

        int month = this.month;

        int day = this.day;

        for (int i = 0; i < n; i++) {

            day++;

            if (day > getDaysOfMonth(year,month)) {

                day = 1;

                month++;

                if (month > 12) {

                    month = 1;

                    year++;

                }

            }

        }

        return new Date(year,month,day);

    }

 

    public Date getNPreviousDays(int n) {

        int year = this.year;

        int month = this.month;

        int day = this.day;

        for (int i = 0;i < n;i++){

            day --;

            if (day < 1) {

                month --;

                if (month < 1) {

                    year --;

                    month = 12;

                }

                day =day + getDaysOfMonth(year,month);

            }

        }

        return  new Date(year,month,day);

    }

 

    public String show(){

        return year+"-"+month+"-"+day;

    }

 

    public int getDaysofDates(Date date,Date anotherDate) {

        int numOfLeapYear = 0;

        int days = 0;

        Date littleDate= date;

        Date largeDate = anotherDate;

        if ((date.year > anotherDate.year) || ((date.year == anotherDate.year) && (date.month > anotherDate.month)) || ((date.year == anotherDate.year) && (date.month == anotherDate.month) && (date.day > anotherDate.day))){

            largeDate = date;

            littleDate = anotherDate;

        }

        for(int i = littleDate.getYear();i < largeDate.getYear();i ++){

            if (isLeapYear(i)){

                numOfLeapYear ++;

            }

        }

        days = (largeDate.getDay() - littleDate.getDay()) + (DayOfMonth[largeDate.getMonth() - 1] - DayOfMonth[littleDate.getMonth() -1]) + (largeDate.getYear() - littleDate.getYear() - numOfLeapYear) * 365 + numOfLeapYear * 366;

        return days;

    }

}

public class Main{

    public static void main(String[] args){

        Scanner input = new Scanner(System.in);

        int choice = input.nextInt();

        if (choice != 1 && choice != 2 && choice != 3){

            System.out.println("Wrong Format");

            return;

        }

        switch (choice){

            case 1:

                int year1 = input.nextInt();

                int month1 = input.nextInt();

                int day1 = input.nextInt();

                Date a = new Date(year1,month1,day1);

                if(!a.checkInputValidity()){

                    System.out.println("Wrong Format");

                    return;

                }

                int n1 = input.nextInt();

                if(n1 < 0) {

                    System.out.println("Wrong Format");

                }

                else {

                    System.out.println(a.getNNextDays(n1).show());;

                }

                break;

 

            case 2:

                int year2 = input.nextInt();

                int month2 = input.nextInt();

                int day2 = input.nextInt();

                Date b = new Date(year2,month2,day2);

                if (!b.checkInputValidity()){

                    System.out.println("Wrong Format");

                    return;

                }

                int n2 = input.nextInt();

                if(n2 < 0) {

                    System.out.println("Wrong Format");

                }

                else {

                    System.out.println(b.getNPreviousDays(n2).show());;

                }

                break;

 

            case 3:

                int year3 = input.nextInt();

                int month3 = input.nextInt();

                int day3 = input.nextInt();

                int year4 = input.nextInt();

                int month4 = input.nextInt();

                int day4 = input.nextInt();

                int year5 = 0;

                int month5 = 0;

                int day5 = 0;

                Date c = new Date(year3,month3,day3);

                Date d = new Date(year4,month4,day4);

                Date e = new Date(year5,month5,day5);

                if(!c.checkInputValidity() || !d.checkInputValidity()){

                    System.out.println("Wrong Format");

                    return;

                }

                int days = e.getDaysofDates(c,d);

                System.out.println(days);

        }

    }

}

 

由于当时对类与类之间的联系还不清楚,在编写代码过程中,编译器始终警告说我创建的对象为空,在看过老师发的正确代码后,发现应该是创建对象的时候没有一层一层创建,于是我为了应急实现功能就做成了一个类class Date()同样能够实现功能,但是功能3有一个测试点未能通过,原因是我的getDaysofDates()方法在处理带有闰年闰月时含有逻辑错误。例如:给到输入3 2002 7 27 2020 7 27,其输出结果应是6575,但输出结果却少了1

 

 

 

这道题目需要注意的点有:在处理前两个功能时,要注意跨年、跨月、闰月等基本情况,这些情况不容易被忽视。而第三个功能则显得比较麻烦,因为要确定两个日期之间具体跨了多少个月——多少个闰月,小月,大月。尽管当时改进了,但还是存在瑕疵。

题目集05 7-5 日期问题面向对象设计(聚合二) (40 分)

参考题目7-3的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:

 

 

 

 

 

 

 

与前者相比,可以发现这里的Year,Month,Day类时相互独立的,这与前者不同,前者属于Year,Month,Day,DateUtil四个类之间相互调用,而此题是直接在DateUtil类中调用其他三个类,这样做的优点是,代码相对简单,不需要很繁琐的循环调用,而前者的优点则是通过类之间的调用体现出了各类的关系,体现的更为清楚。

题目集04 7-3 图形继承 (15 分)

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

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

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

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

输入格式:

共四种合法输入

  • 1 圆半径
  • 2 矩形宽、长
  • 3 球半径
  • 4 立方体宽、长、高

输出格式:

按照以上需求提示依次输出

 

题目集06 7-5 图形继承与多态 (50 分)

掌握类的继承、多态性及其使用方法。具体需求参见作业指导书。

2021-OO第06次作业-5指导书V1.0.pdf

输入格式:

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

输出格式:

  1. 如果图形数量非法(小于0)或图形属性值非法(数值小于0以及三角形三边关系),则输出Wrong Format。
  2. 如果输入合法,则正常输出,输出内容如下(输出格式见输入输出示例):
  • 各个图形的面积;
  • 所有图形的面积总和;
  • 排序后的各个图形面积;
  • 再次所有图形的面积总和。

提交源码:

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);

        ArrayList<Double> areaList = new ArrayList<>();

//        System.out.println("Please input the quantities of geo and the information:");

        int numberOfCircle = input.nextInt();

        int numberOfRectangle = input.nextInt();

        int numberOfTriangle = input.nextInt();

 

        if (numberOfCircle < 0 || numberOfRectangle < 0 || numberOfTriangle < 0){

            System.out.println("Wrong Format");

            return;

        }

        Circle[] circles = new Circle[numberOfCircle];

        Rectangle[] rectangles = new Rectangle[numberOfRectangle];

        Triangle[] triangles = new Triangle[numberOfTriangle];

        int i;

        for (i=0;i<numberOfCircle;i++){

            double radius = input.nextDouble();

            circles[i] = new Circle(radius);

            if (!circles[i].validate()) {

                System.out.println("Wrong Format");

                return;

            }

            areaList.add(circles[i].getArea());

        }

        for (i=0;i<numberOfRectangle;i++){

            double length = input.nextDouble();

            double width = input.nextDouble();

            rectangles[i] = new Rectangle(length,width);

            if(!rectangles[i].validate()){

                System.out.println("Wrong Format");

                return;

            }

            areaList.add(rectangles[i].getArea());

        }

        for (i=0;i<numberOfTriangle;i++){

            double a = input.nextDouble();

            double b = input.nextDouble();

            double c = input.nextDouble();

            triangles[i] = new Triangle(a,b,c);

            if(!triangles[i].validate()){

                System.out.println("Wrong Format");

                return;

            }

            areaList.add(triangles[i].getArea());

        }

        System.out.println("Original area:");

        double sumArea = 0;

        for (i=0;i<numberOfCircle + numberOfRectangle + numberOfTriangle;i++){

            System.out.printf("%.2f ",areaList.get(i));

            sumArea = sumArea + areaList.get(i);

        }

        System.out.println();

        System.out.print("Sum of area:");

        System.out.printf("%.2f",sumArea);

        System.out.println();

        System.out.println("Sorted area:");

        int j;

        for (i=0;i<areaList.size();i++){

            for (j=0;j<areaList.size()-i-1;j++){

                if (areaList.get(j+1) < areaList.get(j)) {

                    Double temp = areaList.get(j);

                    areaList.set(j,areaList.get(j+1));

                    areaList.set(j+1,temp);

                }

            }

        }

        for (i=0;i<areaList.size();i++) {

            System.out.printf("%.2f ",areaList.get(i));

        }

        System.out.println();

        System.out.print("Sum of area:");

        System.out.printf("%.2f",sumArea);

    }

}

 

abstract class Shape {

    public abstract double getArea();

    public abstract boolean validate();

    public abstract String show();

}

 

class Circle extends Shape {

    double radius;

 

    public Circle(double radius) {

        super();

        this.radius = radius;

    }

 

    @Override

    public double getArea() {

        return Math.PI * radius * radius;

    }

 

    @Override

    public boolean validate() {

        if (radius <= 0)

            return false;

        else

            return true;

    }

 

    @Override

    public String show() {

        return String.format("%.2f"+getArea()) + " ";

    }

}

 

class Rectangle extends Shape {

    double length,width;

 

    public Rectangle(double length,double width) {

        super();

        this.width = width;

        this.length = length;

    }

 

    @Override

    public double getArea() {

        return length * width;

    }

 

    @Override

    public boolean validate() {

        if (this.length <= 0 || this.width <= 0)

            return false;

        else

            return true;

    }

 

    @Override

    public String show() {

        return String.format("%.2f"+getArea()) + " ";

    }

}

 

class Triangle extends Shape{

    double a,b,c;

 

    public Triangle(double a,double b,double c) {

        super();

        this.a = a;

        this.b = b;

        this.c = c;

    }

    @Override

    public double getArea() {

        return Math.sqrt((a+b+c)*(a+b-c)*(a+c-b)*(b+c-a))/4;

    }

 

    @Override

    public boolean validate() {

        if ((this.a <= 0 || this.b <=0 || this.c <= 0) || ((this.a + this.b) <= this.c) || ((this.a + this.c) <= this.b) || ((this.b + this.c) <= this.a))

            return false;

        else

            return true;

    }

 

    @Override

    public String show() {

        return String.format("%.2f"+getArea()) + " ";

    }

}

题目集06 7-6 实现图形接口及多态性 (30 分)

编写程序,使用接口及类实现多态性,类图结构如下所示:

 

 

 

其中:

  • 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);

        Circle c = new Circle();

        Rectangle  r = new Rectangle();

        double radius,width,length;

        radius = input.nextDouble();

        width = input.nextDouble();

        length = input.nextDouble();

        c.setRadius(radius);

        r.setLength(length);

        r.setWidth(width);

        if (radius <= 0 || width <= 0 || length <= 0) {

            System.out.println("Wrong Format");

        }

        else {

            System.out.println(String.format("%.2f",c.getArea()));

            System.out.println(String.format("%.2f",r.getArea()));

        }

    }

}

 

interface GetArea {

     double getArea();

}

 

class Circle implements GetArea {

    private double radius;

 

    public Circle() {

    }

 

    public Circle(double radius) {

        this.radius = radius;

    }

 

    public double getRadius() {

        return radius;

    }

 

    public void setRadius(double radius) {

       this.radius = radius;

    }

 

    @Override

    public double getArea() {

        return Math.PI * radius * radius;

    }

}

 

class Rectangle implements GetArea {

    private double length;

    private double width;

 

    public Rectangle() {

    }

 

    public Rectangle(double length,double width) {

        this.length = length;

        this.width = width;

    }

 

    public double getLength() {

        return length;

    }

 

    public void setLength(double length) {

        this.length = length;

    }

 

    public double getWidth() {

        return width;

    }

 

    public void setWidth(double width) {

        this.width = width;

    }

 

    @Override

    public double getArea() {

        return length * width;

    }

}

题目集04 7-3是属于较为基础的继承例题,通过定义一个Shape类为父类并定义一个getArea方法,让子类通过关键字extends继承。由于每种图形的面积求法并不相同,因此需要在子类中重写getArea方法。而一些立体图形具有与平面图形相同的属性(如:BallCircle),则Ball可直接继承CIrcle,这样做的好处是不需要重写getArea方法,而是直接用super关键字调用即可。

题目集06 7-5则较为综合,考察了ArrayList类的用法,抽象类、抽象方法、抽象类定义、实体类构建的运用。需要清楚的是,抽象类里的抽象方法无法被实例化,而在该题目中,每种图形都有自己的面积,但其getArea并不相同,因此getArea应定义为抽象方法,validate同理。而对ArrayList使用冒泡排序,也是需要注意将变量定义为对应类型,使用get.访问成员等ArrayList方法。

题目集06 7-6要求使用接口,接口为特殊类,考察了类与接口间的相连——通过关键字implements

 

题目集06 7-17-3~7-4,考察的是基本的正则表达式,正则表达式匹配数字、字母,总结如下:

英文字母:[a-zA-Z],数字:[0-9],长度{x,y}|表示或,每部分用()区分。

(3)踩坑心得:

1、计算两日期相差多少天时,考虑的不够周全,我一开始考虑的是将年份先循环,if(isLeapYear),numsOfLeapYear++;这样得到了闰年的数量,也就得到了平年的数量,再想用月数相减,日期相减,看似能得出差值,但因为不确定相差的几个月各有多少天,所以无法求得准确值。

 

 

 

2、在主方法中,如果不用访问器setter将输入的值传给各属性,那么即便输入了结果也都是0.00,

 

 

 

 

 

 

 

4)改进建议:

应充分利用多类调用的便捷性,不仅能使代码量减少,也使代码具有层次感,更美观,

而将其全部聚集在一个类里写虽然可行,但可读性较低,不利于改进,

5)总结:通过这三次题目,我学习了ArrayList的基础知识,正则表达式的基本运用,对类与类之间的相互调用更加熟练,感受了封装、多态的优点所在,除此之外,也对之前学习的排序方法,字符串、保留小数位数进行了复习。

 

 

 

 

 

 

 

posted @ 2021-05-02 11:18  MUNICH25  阅读(90)  评论(0)    收藏  举报