java第二次实验总结

 

 

 

 

 

4月23日

 

 

 

个人

作者:20201528-徐长晨

 


OO第二次作业总结

在第二次的总体作业的当中主要就是对于Java进阶性的学习总结,对于接触Java语言由于段时间的我们来水,更好的锻炼我们的编程能力,是我们的编程能力大有提升,所作的题目的难度也更加大,使用的知识也是更加的后面知识也是越来越有趣。

主要只是点有:到了这里不仅是有前面所学的知识使用,对于java面向对象中三大特点:封装、继承、多态的使用,这是非常重要的一点。因为再将来的开发当中就是围绕这三个特别的重要的知识无限的使用。练习类的构造方法、方法的调用、参数传递、对象的构造与使用、练习循环结构、控制结构、练习数据的输入与输出;学习编写结构清晰、逻辑正确、功能完善的java代码、对于java当中的基础语法知识点进行错误探查,从而达到掌握好知识的水平

 本次作业分为以下部分,三次作业实现介绍(包括调度方法), 总结作业。

三次作业的实现

  

题目集4:

1、       水文数据校验及处理 (50 分)      

题目详细:

7-1 水文数据校验及处理 (50 分)

使用Java中的字符串处理类以及正则表达式对输入字符串数据进行合法性校验及计算。(具体需求参见附件 2021-OO第04次作业-1指导书V1.0.pdf )

输入格式:

假定分水口门的数据上报时是采用人工输入的方式,每一行代表一个整点时刻的分水数据,各数据之间采用“|”符号进行分隔,每次可以输入多条数据,直到遇到用户输入“exit”为止,每一行输入数据共包含五部分:测量时间、目标水位、实际水位、开度(包含目标开度和实际开度,以“/”分隔)、流量。 各数据格式要求如下:

  1. 测量时间:格式为“年/月/日 时:分”,其中年份取值范围为[1,9999],“月”与“日”为一位数时之前不加“0”,日期与时间之间有一个空格,“时”与“分”之间采用冒号分隔(英文半角),“时”为一位数时之前不加“0”,“分”始终保持两位,且始终为“00”。注意:“时”数必须是24小时进制中的偶数值。
  2. 目标水位、实际水位、流量:均为实型数,取值范围为[1,1000), 小数点后保留1-3位小数或无小数(也无小数点)
  3. 目标开度、实际开度:实型数,取值范围为[1,10),必须保留2位小数,两个开度之间用“/”分隔

        知识点:这一道题目主要使用的知识就是对于自字符串信息的处理,而这一点再未来开发中也是极为重要的,原因:不管是在现实社会中还是再任何地方都是具有大量数据的,而且基本是以字符串类型的数据处理,本题对于字符串的处理就会需要使用正则表达式来处理信息,正则表达式再批量处理相似类型的数据是非常有作用的,处理的速度以及能力都是非常强大的一种存在。

        正则表达式:就是匹配数据的一种自定义类型的表达式,是自己根据字符串的的特点来自己定义,对于文本信息的处理分析、分段裁剪的操作,从而得到你所需要的信息字符串。

        详细分析题解:本题中题目明确了是对于水文信息的检验和处理,那么就涉及到了你所输入的信息是不是符合正确的格式,当中你所输入的水文信息是错误的形式输入那么程序需要提示出你输入的水文信息是再哪里出现了错误,这样可以给予工组人员提示从而达到即使快速的修改,这大大的节省了人力。当你所输入的水温信息完全没有错误的时候就饿可以输出之前处理水文信息处理的结果,所以在这里就是具有很重要的一点就是需要再检测的时候设置中间变量来赋值说明你的数据是由错误的【这一点是给程序的,在后面判断就可断定是不是要输出处理数据的结果了】,而在这里就可以通过常用的方式布尔Boolean类型来设置中间的处理结果的判断。注意:这里不可以使用return语句直接退出程序,即使你是不需要输出处理数据的结果,但是你需要判断每一段水文信息是在哪里出现了错误。在这里可以使用java当中的方法来进行对于字符串进行分割进行片段的分析处理,这样简化了处理的代码能力。

运行结果:

输入:

 

 

输出:

 

 

2、       日期问题面向对象设计(聚合一) (35 分)

题目详细:

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

 

 

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

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

           知识点:这里主要就是对于类的设计,当中属性、方法完成相应的功能,本题与上一次发布的功能都是一样的,并且使用的知识点大致是一样的,只是本题中增加了知识点是使用类来设计完成程序,这很重要呀,类可是java程序的重要特点。对于类的设计就要主要到封装、继承、多态的使用,这就很好运用到了三大特点。使用了这三大特点就会使程序更加的健壮,功能更灵活,将来对于代码的改动也会更加简易。

           题目详细分析:本题中需要用户自己选择供能,那么就需要这几功能模块,就可以使用switch语句来完成,通过选择的不同进入不同的方法或则类当中执行不同的方法从而达到所想要的效果。,进入类当中,那么类当中就需要完成相应的属性方法的定义,以及方法的实现,对于方法的实现就需要使用到不同的方法,计算方式来完成计算结果的返回到主程序当中。注意了:再进行相应的方法当中计算结果之前需要检验用户输入的日期信息是不是正确合法的,非法输入的话那就不需要进行计算处理了。

运行结果:

样例1:

样例2:

 

样例3:

 

 

 

3、       图形继承

题目详细:

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

题目详细分析:本题当中题目明确了是图形的继承,那么就涉及到了继承,继承extends关键字的使用,继承:就是子类继承父类的作用,那么子类就可以使用父类当中的方法属性等等作用啦在使用继承的时候一定要明确两个类是不是有子类和父类的关系,才可以完成继承,而在本题当中图形是一个很广泛的定义,对于圆形、三角形、矩形等等都是图形,其当中不同的图形是有共同点也是有不同点,那么在这个共同点当中对于我们编写程序计算面积可能是相同的编写过程,那么在这里我们就可以定义一个类:图形类为父类,而其他的各种图形就是子类来继承父类【图形类】,再子类当中定义=各种的属性和方法可能都是与父类当中是相同的那么子类就可以不需要谢写啦,直接使用父类当中的就可以啦

运行结果:

样例1:

样例2:

样例3:

 

题目集4的代码区域:

     No1:

import java.util.ArrayList;

import java.util.Collection;

import java.util.Iterator;

import java.util.Scanner;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) {

        int f1 = 0;int f2 = 0;int f3 = 0;int f4 = 0;int f5 = 0;int f6 = 0;

        Double totalWaterFlow = 0.0;

        Double muBiao = 0.0;

        Double shiJi = 0.0;

        int sumOut = 0;

        int hasWrong = 0;int oneHasWrong = 0;

        String str = "2015/8/2 6:00|133.840|133.080|11.11/1.11|72.8a0";

        Scanner input = new Scanner(System.in);

        Double maxShuWei = 0.0;

        ArrayList c = new ArrayList();/* 创建集合数组对象 */

        String news = input.nextLine();

        while (!(news.equals("exit"))) {  c.add(news);news = input.nextLine();  }

        //c.add("exit");

        Iterator t =c.iterator();

        for(int ii =0; ii < (c.size()); ii++){

            oneHasWrong = 0;sumOut=0;

            Object obj = t.next();

            if(obj instanceof  String){str = ((String)obj).trim();}

            if(str.matches("^\\s*|\\s*$")) {                    //判断连续输入为空

            System.out.println("Max Actual Water Level:0.00");          //判断连续输入为空

            System.out.println("Total Water Flow:0.00");

        }

            String[] pattern = {"([0-9]+)(\\/)([0-9]+)(\\/)([0-9]+)(\\s)([0-9]+)(:)([0-9]+)",

                    "(\\|)((\\s*)?)([0-9]+)(\\.?)([0-9]+)",

                    "(\\|)([0-9]+)(\\.?)([0-9]+)(\\/)([A-Za-z0-9]+)(\\.?)([0-9]+)"};

            Pattern r = null;  String[] s = new String[5];  int j = 0;  String temp = str;

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

                if(i == 0) {

                    r = Pattern.compile(pattern[0]);

                 }else if (i == 3) {

                    r = Pattern.compile(pattern[2]);

                 }else {

                    r = Pattern.compile(pattern[1]);

                }

                Matcher m = r.matcher(temp);

                if(m.find()) { s[j] = m.group(); temp = temp.substring(s[j].length());j++;}

            }

            //if(j != 5){System.out.println("Wrong Format"); System.out.println("Data:" +str); System.exit(0);}

            int[] monthDay = {0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

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

                if(i == 0){

                    s[i] = s[i].trim();

                    String regular = "((([1-9][0-9]{0,3}))/((((1[0-2]|[1-9]))/(([1-2][0-9]|30|[1-9])))) ((([02468]|1[02468]|2[02]|):00)))";

                    if(!s[i].matches(regular))

                        { System.out.println("Row:"+(ii+1)+",Column:1Wrong Format");f1 = 1; }

                }

                if(i == 1){

                    /* 还用正则表达式来求  |133.8400  */

                    s[i] = s[i].substring(1);

                     s[i] = s[i].replaceAll(" ","");

                    String regular = "[1-9]([0-9]?)([0-9]?)(\\.)?[0-9]([0-9]?)([0-9]?)";

                    if(!s[i].matches(regular))

                        { System.out.println("Row:"+(ii+1)+",Column:2Wrong Format");f2 = 1; }

                }

                if(i == 2){

                    // |133.070

                    s[i] = s[i].substring(1);

                    s[i] = s[i].replaceAll(" ","");

                    String regular = "[1-9]([0-9]?)([0-9]?)(\\.)?[0-9]([0-9]?)([0-9]?)";

                    if(!s[i].matches(regular))// 不满足就是输出错误

                        { System.out.println("Row:"+(ii+1)+",Column:3Wrong Format");f3 = 1; }

                    if(f3 == 0 && Double.parseDouble(s[i]) > maxShuWei){

                        maxShuWei = Double.parseDouble(s[i]);

                    }

                }

                if(i == 3){

                    // |1.11/1.21

                    s[i] = s[i].substring(1);

                     s[i] = s[i].replaceAll(" ","");

                    String[] mbf = s[i].split("/");// mbf 每部分  其实就两部分,目标开度、实际开度

                    for (int k = 0; k < mbf.length; k++) {

                        if(k == 0){// 目标开度 --> |1.11

                            String regular = "[1-9](\\.)?[0-9]?([0-9]?)";

                            if(!mbf[k].matches(regular))// 不满足就是输出错误

                                { System.out.println("Row:"+(ii+1)+",Column:4Wrong Format");f4 = 1; }

                            else

                                { muBiao = Double.parseDouble(mbf[k]);}

                        }

                        if(k == 1) {// 实际开度 --> 1.21

                            String regular = "[1-9](\\.)?[0-9]?([0-9]?)";

                            if(!mbf[k].matches(regular))// 不满足就是输出错误

                                { System.out.println("Row:"+(ii+1)+",Column:5Wrong Format");f5 = 1; }

                            else

                                { shiJi = Double.parseDouble(mbf[k]); }

                        }

                    }

                    if(shiJi > muBiao)  sumOut++;

                }

                if(i == 4){

                    // |75.780

                    s[i] = s[i].substring(1);

                     s[i] = s[i].replaceAll(" ","");

                    String regular = "[1-9]([0-9]?)([0-9]?)(\\.)?[0-9]([0-9]?)([0-9]?)";

                    if(!s[i].matches(regular))

                        { System.out.println("Row:"+(ii+1)+",Column:6Wrong Format");f6 = 1; }

                    if(f6 == 0){/* 求出流量,再加到总流量里去 */

                        Double flow = Double.parseDouble(s[4]);

                        totalWaterFlow = totalWaterFlow + 2*60*60*flow;

                    }

                }

            }

            if(f1==0 && f2==0 && f3==0 && f5 == 0 && f4 ==0 && f6==0 && shiJi > muBiao)// 就说明开度出现了问题就提示错误

             {

                 for (int i = 0; i < sumOut; i++)

                    { System.out.println("Row:"+(ii+1)+" GateOpening Warning"); }

             }

            if(f1==1 || f2==1 || f3==1 || f4==1 || f5==1 || f6==1){ hasWrong++;  oneHasWrong++; }

            if(oneHasWrong != 0) System.out.println("Data:"+str);

            f1 = 0;f2=0;f3 = 0;f4=0;f5=0;f6=0; oneHasWrong = 0;

        }

        if(hasWrong == 0){  System.out.println("Max Actual Water Level:" +String.format("%.2f",+maxShuWei));/* 输出最大的水位信息 */

            System.out.println("Total Water Flow:" +String.format("%.2f",+totalWaterFlow));}

    }

    public static boolean isLeapYear(int year){  return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; }

}

No2:

 

import java.util.Scanner;

 

/**

 * 需求:求n天后日期

 *      求n天前日期

 *      求两个日期之差天数

 */

public class Main {

    /**

     * 在main单中如何·调用方法

     *      - 输入选择是什么功能

     *      - 进入相应的语句进行判断

     *          * 首先是输入日期

     *          * 其次是判断日期是不是正确合法

     *          * 在来就是进行相应的语句条件确认

     */

    public static void main(String[] args) {

        Scanner s = new Scanner(System.in);

        int userChoice = s.nextInt();

        // 创建计算对象

        if(userChoice == 1){

            // 进入第一种状态:计算下n天的日期

            // 先输入日期

            int year = s.nextInt(); int month = s.nextInt(); int day = s.nextInt();

            // 输入n天要开始计算了

            int n = s.nextInt();

            // 创建第一个日期对象

            DateUtil du = new DateUtil(year,month,day);

            // 在检查日期是否合法

            if(!du.checkInputValidity()){

                // 不正确,提示,退出程序

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

                System.exit(0);

            }

            // 调用方法,开始计算,就是传参 n

            // 创建对象来接收这个返回值

            DateUtil date = du.getNextNDays(n);

            // 接下来就是格式化输出答案,我采用的是重写toString方法

            System.out.println(date);

        }else if(userChoice == 2){

            // 进入第二种状态:计算前n天的日期

            // 先输入日期

            int year = s.nextInt(); int month = s.nextInt(); int day = s.nextInt();

            // 输入n天要开始计算了

            int n = s.nextInt();

            // 创建第一个日期对象

            DateUtil du = new DateUtil(year,month,day);

            // 在检查日期是否合法

            if(!du.checkInputValidity()){

                // 不正确,提示,退出程序

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

                System.exit(0);

            }

            // 调用方法,开始计算,就是传参 n

            // 创建对象来接收这个返回值

            DateUtil date = du.getPreviousNDays(n);

            // 接下来就是格式化输出答案,我采用的是重写toString方法

            System.out.println(date);

        }else if(userChoice == 3){

            // 进入第三种状态:计算下两个日期是天数差

            // 先输入日期

            int year = s.nextInt(); int month = s.nextInt(); int day = s.nextInt();

            // 创建第一个日期对象

            DateUtil du = new DateUtil(year,month,day);

            // 在输入日期

            int year1 = s.nextInt(); int month1 = s.nextInt(); int day1 = s.nextInt();

            // 创建第一个新的日期对象

            DateUtil date = new DateUtil(year1,month1,day1);

            // 在检查日期是否合法

            if(!du.checkInputValidity() || !date.checkInputValidity()){

                // 不正确,提示,退出程序

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

                System.exit(0);

            }

            // 调用方法,开始计算,就是传参data

            // 创建对象来接收这个返回值

            /**

             * 1、在对比两个日期是不是相等的

             *      - 相等就直接输出0推出程序

             *  2、先对比啦两个日期的大小

             *     - 前小后大就交换

             *

             */

            if(du.equalsDates(date)){

                // 说明两个日期相等

                System.out.println(0);

                System.exit(0);

            }

            // 到这里就不相等,那比较交换

            // 返回 true就是前比后大    返回 false就是前比后小

            if(!du.compareDate(date)){

                // 说明前比后小,那就交换

                DateUtil temp = new DateUtil();

                temp = du; du = date; date = temp;

            }

            // 到这就正常的去调用方法,接受返回值 int

            int sumDay = du.getDaysofDates(date);

            System.out.print(sumDay);

        }else{

            // 错误选择就是提示一下,退出程序

            System.out.println("您做出的选择有误!!!");

            return;

        }

    }

}

 

// DateUtil类

/*

因该有的东西:

    - 构造方法、set and get方法

    - 计算n天数的日期方法

        * 前n天

        * 后n天

    - 计算两个日期之间相差的天数方法

        * 这里就是看main方法当中的调用问题,反正我先把这些方法都写进入

    - 判断闰年的方法

        * 判断闰年了还要判断月份的问题是【2月】 还是 【非2月】

    - 判断输入的日期是是否合法

    -

//3 2014 2 14 2020 6 14

 */

class DateUtil{

    private int year;

    private int month;

    private int day;

    // 定义为非闰年的每月天数

    int[] monthDay = {0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    // 重写toString方法

 

    @Override

    public String toString() {

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

    }

 

    // 无参构造方法

    public DateUtil() { }

    // 有参构造方法

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

        this.year = year;

        this.month = month;

        this.day = day;

    }

    // set and get

    public int getYear() { return year; }

    public void setYear(int year) { this.year = year; }

    public int getMonth() { return month; }

    public void setMonth(int month) { this.month = month; }

    public int getDay() { return day; }

    public void setDay(int day) { this.day = day; }

 

    // 判断闰年方法

    public boolean isLeapYear(int year){

        // 是闰年返回true

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

    }

 

    // 判断是日期输入合法日期

    public boolean checkInputValidity()//检测输入的年、月、日是否合法

    {

        /**

         * 合法 返回true

         * 不合法返回false

         */

        if (year < 1900 || year > 2050 ) return false;

        // 是闰年并且是2月

        if(month < 1 || month > 12 ) return false;

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

            return day >=1 && day <=29;

        }else if(!isLeapYear(this.year) && this.month == 2){

            return day >=1 && day <=28;

        }

        // {0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

        // 不是闰年而且不是2月 但是还有大月小月之分

        if(month == 4 || month == 6 || month == 9 || month == 11)

            return day >=1 && day <=30;

        return day >=1 && day <=31;

       

    }

 

    // 比较两个日期的大小【前后】

    public boolean compareDate(DateUtil dateUtil){

        /*

       一 这里做的目的就是要规定要前一个日期一定要比后一个日期大这样才好用前一个日期来减后一个日期 计算

        前个年份比后个年份小--> 就不能用前"日期" 对比后一个 "日期"

        返回 true就是前比后大

        返回 false就是前比后小

         */

 

        if(this.year < dateUtil.year) return false;

        // 两个年份相同就要看月份和天数的问题了

        if(this.year == dateUtil.year){

            // 前月小于后月

            if(this.month < dateUtil.month) return false;

            if(this.month == dateUtil.month){

                if(this.day < dateUtil.day) return false;

            }

            // 可以到这里就会说明前月大于后月那就不需要对比了,前日期一定会不后日期大-->就可以用后一个日期来减后一个日期

            return true;

        }

        // 鞥到这就一定说明前比后大

        return true;

    }

 

    // 比较连个日期是否相等

    public boolean equalsDates(DateUtil dateUtil){

        /*

        相等的话就直接输出0,而不用在进行之后的代码来计算天数差。

        大大节省了代码的运行时间,对于代码的优化就很好

         */

       if(this.year == dateUtil.year && this.month == dateUtil.month && this.day == dateUtil.day)

           return true;

       // 能到这里就说明连个日期是不相等的,那我就返回false

       return false;

    }

 

    // 计算两个日期的相差天数

    public int getDaysofDates(DateUtil date){

        int nday = this.day;

        int nmonth = this.month;

        int nyear = this.year;

        /**

         * 在这里一定是前日期比后日期更大,因为我在main方法当中就已经经过了判断,传参而来就是这样的

         * 其实也可以在这里进行对比操作,其实效果一样完全相同-->只是判断的2位置不不相同而已

         *  this.yearc > date.year

         *  this.month > date.month

         *  this.day > date.day

         */

        /*

        怎么计算相隔天数呢!

            - 每一个月的天数相加在加上该月的天数day,然后每年的天数相加

            - 注意:到了小日期的那个年份是就不能在直接相加每一年的天数了

         */

        // 这样的话没有开始加天就是年相等了就是说明  【 this.month > date.month 】

        int sumDay = 0;

        if(this.year == date.year){

            // 闰年2月天数

            // 道理同下,就是在不是闰年的情况下也把2月天使当作闰年2月天数来计算就会导致错误

            this.monthDay[2] = 28;// 修改之前没有加上这一行-- 【其实这里加不加都是不一样的】

            if(isLeapYear(nyear)) this.monthDay[2] = 29;

 

            while(this.month >= date.month){

                // 说明走到了这一天【同一个日期】,那就·返回总天数

                if(nday == date.day && nmonth == date.month && nyear == date.year) return sumDay;

                nday--;sumDay++;

                // 天数为0置为前一个月

                if(nday == 0){

                    nmonth--;

                    nday = monthDay[nmonth];

                    // 约束为0后退一年,同时月份赋值12

                    if(nmonth == 0){

                        nyear--;

                        nmonth=12;

                    }

                }

            }

            // 到了这就说明this.month < date.month 其实不会有这样的情况

            return sumDay;

        }

        // 说明前年比后年分大

        while(true){

            // 闰年2月天数

            // 道理同上、同下 也是闰年非闰年2月的天数错误  行数:308 -- 238

            this.monthDay[2] = 28;// 修改之前没有加上这一行

            if(isLeapYear(nyear)) this.monthDay[2] = 29;

            // 月份的推演

           while(nmonth != 0){

               // 天数的推演

               while (nday != 0){

                   sumDay++;nday--;

                   // 没对于nday nmonth nyear 进行了改变就要对两个现在的日期进行对比,看是不是相等了 return就是直接推出了本方法

                   if(nday == date.day && nmonth == date.month && nyear == date.year) return sumDay;

               }

               // 到了这里就说明走完了一个月(原因是:nday == 0)。那么就要对月份天数进行改动

               nmonth--; nday = this.monthDay[nmonth];

               // 同上方道理

               if(nday == date.day && nmonth == date.month && nyear == date.year) return sumDay;

           }

           // 到了这里说明走完了一年,(原因是nmonth == 0)。那就要对年份、月份、天数进行改变

            nyear--; nmonth = 12; nday = monthDay[12];

            if(nday == date.day && nmonth == date.month && nyear == date.year) return sumDay;

        }

        // 到了这里就一定是:nyear < date.year

 

    }

 

    // 计算下n天的日期

    public DateUtil  getNextNDays(int n){

        /*

        定义为换回DateUtil的原因是:

            - 我要换回的是计算后的n天日期就要返回三个信息就刚好的是我就new DateUtil对象很好满足我的需求

         */

        // 首先我需要得到现在的日期是什么,然后对其进行操作最后返回、

        int nday = this.day;

        int nmonth = this.month;

        int nyear = this.year;

        /**

         * 这是之前这样写的,这样子就错了,因为我在这个对象中定义的数组,要是有一次是闰年的话我就直接把2月赋值为29天

         * 但是在不是闰年的情况下我计算的话就会导致,这一年2月还是个以闰年29来计算,就会导致最后求出来的答案是有错误的

         * 而且这个答案是有很大偏差的

         * 这一个点是很值得去记忆的

         */

        /*if(isLeapYear(this.year)){

            //说明是闰年我就要修改2月天数为29天

            this.monthDay[2] = 29;

        }*/

 

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

            // 正常的情况下,是在不管是不是闰年的情况下就要赋值为不是闰年的2月天数,而后在判断是不是闰年的情况

            this.monthDay[2] = 28;// 修改之前没有加上这一行      ----   【最开始的在修改的地方】   -----

            if(isLeapYear(nyear)){

                //说明是闰年我就要修改2月天数为29天

                this.monthDay[2] = 29;

            }

            nday++;

            // 如果天数大于这个月天数了就天数置为1,月数加1

            if (nday > this.monthDay[nmonth]) {

                nday = 1;

                nmonth++;

                // 道理同上

                if (nmonth > 12) {

                    nmonth = 1;

                    nyear++;

                }

            }

        }

        // 到了这里就计算完成了新的日期

        return  new DateUtil(nyear,nmonth, nday);

    }

 

    // 计算前n天的日期

    public DateUtil getPreviousNDays(int n){

        int nday = this.day;

        int nmonth = this.month;

        int nyear = this.year;

        // 道理同上一个方法                                  ----   【行数: 308】   -----

        /*if(isLeapYear(this.year)){

            //说明是闰年我就要修改2月天数为29天

            this.monthDay[2] = 29;

        }*/

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

            // 正常的情况下,是在不管是不是闰年的情况下就要赋值为不是闰年的2月天数,而后在判断是不是闰年的情况

            this.monthDay[2] = 28;// 修改之前没有加上这一行   ----   【行数: 308】   -----

            if(isLeapYear(nyear)){

                //说明是闰年我就要修改2月天数为29天

                this.monthDay[2] = 29;

            }

            nday--;

            if (nday == 0) {

                nmonth--;

                // nday = this.monthDay[nmonth];

                // 上面这一句话要是这么写的话就出现了错误,因为在这个点nmonth可能为0 ,这样的话nday也就为0了就不符合了

                // 道理同上

                if (nmonth == 0) {

                    nmonth = 12;

                    nyear--;

                }

                nday = this.monthDay[nmonth];

 

            }

        }

        return new DateUtil(nyear,nmonth,nday);

    }

// Day类 class Day{ }

// Month类 class Month{ }

// Year类  class Year{ }

运行结果:

样例1:

 

样例2:

 

样例3:

 

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

         

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

 

       题目详细分析:本题与上一题基本完全一致。

       与上一题对比:上一题类设计,而这题当中虽然也是类设计但是可以很好的使用到继承,而继承就是为了节省大量的重复写相同相似代码的过程,子类可以通过父类当中的属性、方法直接使用,这样就增强了代码的健壮性、可读性,所以使用继承来编写代码是对于程序员来说是很友好的操作,大量的节省了程序员编写的次数,大大提高了编写程序的效率。而在第二题当中父类当中使用了更多的构造方法,普通的方法,对于子类可以很好的继承方法,而自己基本不需要写特别的放啊,只需要重写覆盖父类的方法就可以了。

 

题目集6:

17-5 图形继承与多态 (50 分)

题目详细:

输入格式:

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

 

 

输出格式:

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

题目详细分析:本题中与上一次的图形继承基本设计编写逻辑相同,而在其增加了的就是使用了多态机制:多态就是不管你现在要是使用的子类是什么,我在创建对象的时候都是以父类的形式来创建,而直接通过来调用父类中有的方法,而在子类当中需要写的就是继承父类的方法来重写从而达到计算图形面积的作用,而再main方法看上去调用的是父类当中的方法来计算面积,但是程序底层调用的是子类当中已经进行重写了的方法,从而可以达到计算的额面积是准确无误的,如果父类的对象想要调用子类当中特有的方法,那么就需要对于这个对象进行强制类型转换,这样现在这个对象不仅在底层上是子类的对象,在表面也是子类的相应对象,直接可以通过这个对象引用来直接调用子类当中的方法。

输入:1 1 1 2.3 3.2 3.2 6.5 3.2 4.2
输出: Original area:
      16.62 10.24 5.68 
      Sum of area:32.54
      Sorted area:
      5.68 10.24 16.62 
      Sum of area:32.54

运行结果:

样例1:

 

样例2:

 

样例3:

 

 

 

 

2、7-6 实现图形接口及多态性 (30 分)

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

 

 

 

其中:

  • GetArea为一个接口,无属性,只有一个GetArea(求面积)的抽象方法;
  • Circle及Rectangle分别为圆类及矩形类,分别实现GetArea接口
  • 要求:在Main类的主方法中分别定义一个圆类对象及矩形类对象(其属性值由键盘输入),使用接口的引用分别调用圆类对象及矩形类对象的求面积的方法,直接输出两个图形的面积值。(要求只保留两位小数)

          题目详细分析:本题还是与上一题是完全一样的,只是在设计的时候更加的完善了,使用接口的方式,这样更加符合一句话:面象接口编程。这样做就使程序更加的抽象,但是这样对于代码的逻辑性是更加的强的,更加的严谨,使用操作程序的效率是更加的高效的,对于我们在任何时候都要关注的问题就是:代码的安全性也是有非常高的性能。这样做使方法更加的抽象了,这样在创建对象的时候、在调用方法的时候都更加的有操作性,代码逐渐的变得越来越健壮。

运行结果:

样例1:

    

样例2:

 

代码:

  7-6 实现图形接口及多态性 (30 ):

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);

        double r = input.nextDouble(), = input.nextDouble(), = input.nextDouble();

        if(r<=0 || <=0 || <=0){

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

            System.exit(0);

        }

        // 创建对应的对象和

        Circle c= new Circle(r);

        Rectangle rt = new Rectangle(, );

        System.out.printf("%.2f\n", c.getArea());

        System.out.printf("%.2f\n",rt.getArea());

    }

}

// 定义getArea接口

interface GetArea{

    public double getArea();

}

// Circle

class Circle implements GetArea{

    private Double radius;

    //构造方法

    public Circle(){ }

    public Circle(Double radius)

    { super();this.radius = radius; }

    // set and get

    public Double getRadius() { return radius; }

    public void setRadius(Double radius) { this.radius = radius; }

 

    @Override

    public double getArea()

        { return Math.PI * this.radius * this.radius; }

}

class Rectangle implements GetArea {

    private Double width;

    private Double length;

    // 构造方法

    public Rectangle() { }

    public Rectangle(Double width, Double length)

    { this.width = width;this.length = length; }

 

    // set abd get

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

    // 重写方法

    @Override

    public double getArea()

    { return this.length * this.width; }

 

 

7-5 图形继承与多态:

 

import java.util.*;

import java.util.stream.Collector;

 

public class Main{

    public static void main(String[] args) {

        Scanner s = new Scanner(System.in);

        int CircleCount = s.nextInt(),RectangleCount = s.nextInt(),TriangleCount = s.nextInt();

        if(CircleCount<0 || RectangleCount<0 || TriangleCount<0)

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

                System.exit(0);

            }

        ArrayList<Circle> circleList = new ArrayList<>();

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

            double r = s.nextDouble();

            Circle c = new Circle(r);

            circleList.add(c);

        }

        ArrayList<Rectangle> rectangleList = new ArrayList<>();

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

            double 长 = s.nextDouble();

            double 宽 = s.nextDouble();

            Rectangle r = new Rectangle(长,宽);

            rectangleList.add(r);

        }

        ArrayList<Triangle> triangleList = new ArrayList<>();

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

            double a = s.nextDouble(),b = s.nextDouble(),c = s.nextDouble();

            Triangle t = new Triangle(a,b,c);

            triangleList.add(t);

        }

        /* 创建面积集合对象,用来保存每一个图形的面积[只是用来储存面积]

           这里后面是需要排序的,,所有选用自定义比较器 或者 定义接口实现类来重写competeTo方法

        */

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

        // 园面积Circle

        for (Circle c : circleList) {

            if(c.getRadius() <= 0){

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

                System.exit(0);

            }

            // 到了这里就说明输入是正确的,那就保存面积

            areaList.add(c.getArea());

        }

        // 矩形面积Rectangle

        for (Rectangle r : rectangleList) {

            if(r.getLength()<0 || r.getWidth()<0){

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

                System.exit(0);

            }

            // 到了这里就说明输入是正确的,那就保存面积

            areaList.add(r.getArea());

        }

        for(Triangle t : triangleList){

            if(!t.check合法()){

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

                System.exit(0);

            }

            // 到了这里就说明输入是正确的,那就保存面积

            areaList.add(t.getArea());

        }

        double sumArea = 0;

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

        for (double d : areaList) {

            sumArea = sumArea + d;

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

            System.out.print(" ");

        }

        System.out.printf("\nSum of area:%.2f\n",sumArea);

        Collections.sort(areaList,new MyComparator());

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

        for (double d : areaList) {

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

            System.out.print(" ");

        }

        System.out.printf("\nSum of area:%.2f\n",sumArea);

    }

}

// 写一个比较器

class MyComparator implements Comparator<Double>{

    @Override

    public int compare(Double o1, Double o2)

        { return (int) (o1-o2); }

}

// Shape类返还0.0

        class Shape{

            public Shape() { }

            public Double getArea()

            { return 0.0; }

        }

        class Triangle extends Shape{

            double a,b,c;

            // 构造方法

            public Triangle() { }

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

                { this.a = a;this.b = b;this.c = c; }

            // set and get

            public double getA() { return a; }

            public void setA(double a) { this.a = a; }

            public double getB() { return b; }

            public void setB(double b) { this.b = b; }

            public double getC() { return c; }

            public void setC(double c) { this.c = c; }

            @Override

            public Double getArea()

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

            public boolean check合法() {

                double a[] = new double[3];

                a[0] = this.a;a[1] = this.b;a[2] = this.c;

                Arrays.sort(a);

                if (a[0] + a[1] > a[2])

                    { return true; }

                else

                    { return false; }

            }

        }

//Circle继承Shape

        class Circle extends Shape {

            private Double radius;

            //构造方法

            public Circle(){ }

            public Circle(Double radius)

                { super();this.radius = radius; }

            // set and get

            public Double getRadius() { return radius; }

            public void setRadius(Double radius) { this.radius = radius; }

            //重写父类方法求园面积

            @Override

            public Double getArea()

                { return Math.PI * this.radius * this.radius; }

        }

// 子类Rectangle 继承父类Shape

        class Rectangle extends Shape {

            private Double width;

            private Double length;

            // 构造方法

            public Rectangle() { }

            public Rectangle(Double width, Double length)

                { this.width = width;this.length = length; }

 

            // set abd get

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

            // 重写方法

            @Override

            public Double getArea()

                { return this.length * this.width; }

        }

        class Ball extends Circle {

            public Ball() { }

            public Ball(Double radius) { this.setRadius(radius); }

            @Override

            public Double getArea()

                { return 4 * Math.PI * this.getRadius() * this.getRadius(); }

            // 自定义方法求体积

            public double getVolume()

                { double r=getRadius();return 4.0/3.0*r*r*r*Math.PI; }

        }

 

        class Box extends Rectangle {

            private double heigth;

            public Box(Double width, Double length, double heigth)

                { this.heigth = heigth; }

            public Box(){ }

            public double getHeigth() { return heigth; }

            public void setHeigth(double heigth) { this.heigth = heigth; }

            @Override

            public Double getArea() {

                Double area = 2*this.heigth*this.getLength() + 2*this.heigth*this.getWidth() + 2*this.getWidth()*this.getLength();

                return area;

            }

            // 自定义方法求立方体体积

            public double getVolume()

                { return this.heigth*this.getWidth()*this.getLength(); }

        }

// 自定i异常类,输入的数据范围异常

        class dateRangeException extends Exception{

            public dateRangeException(){}

            public dateRangeException(String s)

                { super(s); }

        }

 

 

 

 

 

 

posted @ 2021-05-01 23:09  小晨Yu呀!  阅读(307)  评论(0)    收藏  举报