第二次Blog

一、作业总结

这三次题目集较第一次作业难度有进一步提高,考察抽象类、接口等。在写这次作业的同时,不仅要在较短的时间内学习相关知识点,还要会掌握,确实有点难度。题目集4在一次考察对正则表达式的使用,但是相较之前的多项式求导,难度有所降低,但题目复杂程度依然不减。题目集4还考察了继承的用法。题目集5主要依然是考察正则表达式的运用。题目集6旨在掌握类的继承、多态性及其使用方法、使用接口及类实现多态性。

从结果来看,虽然每道题都有认真完成,但有几道题还未能拿到满分。

二、题目分析

下面对三次作业做个简要的分析。

1.日期问题面向对象设计(聚合一)(题目集4

由于老师在题目上给了类图,所以对于代码的整体有个比较明确的框架思路也非常清晰,有个明确的方向。唯一需要注意的是相关方法里的算法,注意算法是否错误。一开始,由于我的算法上存在一些错误,一直没有办法通过。后来仔细重新看了下题目,由于范围的看错导致浪费了很多不必要的时间。

public void resetMin(){//日期复位

        value = 1;

    }

    public void resetMax(){//日期设为该月最大值

        value = mon_maxnum[month.getValue()-1];

    }

public void dayIncrement(){//日期增1

        value++;

    }

    public void dayReduction(){//日期减1

        value--;

    }

public void resetMin(){//月份复位

        value = 1;

    }

    public void resetMax(){//月份设置为12

        value = 12;

    }

public void monthIncrement(){//月份增1

        value++;

    }

    public void monthReduction(){//月份减1

        value--;

    }

public void yearIncrement(){//年份增1

        value++;

    }

    public void yearReduction(){//年份减1

        value--;

}

对于以上这些方法,我并没有用到,但有一些方法内可以用到,但语句过于长所以我认为用不到。在以后的写题过程中如果没有强制要求,我个人认为其实可以不用特意使用。

另外,在以下代码中

public boolean validate() {

        if(this.getMonth().getYear().isLeapYear())

            mon_maxnum[1]++;

        if(value >= 1 && mon_maxnum[month.getValue()-1] >= value)

            return true;

        return false;

    }

前一次作业中我没有用上这个mon_maxnum[]这个数组,导致代码过于简单且繁多,使用后代码精简了不少,提高了代码的复杂性。

Main类结构:

 

 

 

 

 

通过报告中可知,红线处的代码还需要做改良。

2.图形继承(题目集4

该题旨在实现图形类的继承。使用继承,可以减少代码量,常用方法可以不必定义,直接继承父类定义好了的方法,提高了编程效率,体现了软件的三特性之一的可复用性。掌握了用法后,这道题难度并不大。

class Shape{

    public void Shape(){

        System.out.println("Constructing Shape");

    }

    public double getArea()//求图形面积

    {

        return 0.0;

    }

 

}

class Circle extends Shape{

    public void Circle(){

        System.out.println("Constructing Circle");

    }

    private double radious;

 

    public Circle(){

    }

    public Circle(double radious){

        this.radious = radious;

    }

    public void setRadious(double radious) {

        this.radious = radious;

    }

    public double getRadious() {

        return radious;

    }

    @Override

    public double getArea(){

        return Math.PI*radious*radious;

    }

}

如上代码所示,子类继承父类时,从父类继承的方法前需加上@Override。在java中,@Override注解是用来指定方法重写的,只能修饰方法并且只能用于方法重写,不能修饰其他的元素,它可以强制一个子类必须重写父类方法或者实现接口的方法。并且,@Override的作用是告诉编译器检查这个方法,保证父类要包含一个被该方法重写的方法,否则就会编译错误,这样可以帮助我们避免一些低级错误。一开始,我有忘记在方法前面加@Override注解,后来发现即便是方法编辑错误了,编译器也不会有提示,这时Shape父类的getArea()方法并没有被重写,将会引起程序出现Bug。子类必须说明extends父类。extends:关键字,继承的意思。子类中定义一个与父类同名,返回类型,参数类型均相同的一个方法,称为方法的覆盖。方法的覆盖发生在子类与父类之间。另外,可使用如下说明的super提供对父类的访问。

class Box extends Rectangle{

    public void Box(){

        System.out.println("Constructing Box");

    }

    double height;

    public Box(){

    }

    public Box(double heiget){

        this.height = heiget;

    }

 

    public void setHeight(double height) {

        this.height = height;

    }

 

    public double getHeight() {

        return height;

    }

    @Override

    public double getArea(){

        double length0 = getLength();

        double width0 = getWidth();

 

        return length0*width0*2+length0*height*2+width0*height*2;

    }

    public double getVolume()//求立方体体积

    {

        return super.getArea()*height;

    }

}

最后一个方法中的语句return super.getArea()*height;是使用了父类Rectangle的方法。在javasuper代表父类存储空间的标识(可以理解为父类引用可以操作父类的成员)。在这里要和this区分开来。

this

(1)属性访问:访问本类中的属性,如果本类中没有此属性,则从父类中继续查找。

(2)方法:访问本类中的方法,如果本类中没有此方法,则从父类中继续查找。

(3)调用构造:调用本类构造,必须放在构造方法的首行。

(4)首行:表示当前对象。

super

(1)属性访问:访问父类中的属性。

(2)方法:直接访问父类中的方法。

(3)调用构造:调用父类构造,必须放在子类构造方法的首行。

用法:

this.成员变量:调用本类的成员变量。而super.成员变量:调用父类的成员变量。

示例:

super可以用来直接引用父类的实例变量。eg:super.name;

super可以用来直接调用父类的方法。eg.super.get();

super()可以用于直接调用父类构造的函数。eg:super();

superthis的区别:

(1)代表的实物不同:

super代表的是父类空间的引用。

this代表的是所属函数的调用者对象。

(2)使用前提不同:

super必须要有继承关系才能使用。

this不需要继承关系也能使用。

(3)调用的构造函数不同:

super:调用父类的构造函数。

this:调用所属类的构造函数。

 

 

Main类结构:

 

 

 

 

 3.统计JAVA程序中关键词的出现次数(题目集5

这道题不仅考察正则表达式的运用,还考察对ListSetMap的使用。

对于这道题树立正确的思路非常重要。以下是我的大致思路:

1)使用final声明是关键字数组,可以保证数组内的元素在使用中不被改变。

2)说明与初始化(使用HashMap用于保存关键字与出现次数,例如:<key,value> = <int,3>)。

3)关键字筛查:读取输入文本的某一行,将该行split为字符串数组,逐个判断是否为关键字,但是首先需要去除非字母和数字字符的影响。

4)处理注释:读取文本中的每一行,首先判断是否属于注释,若属于则跳过,则不属于则进行关键字筛查。

代码参考如下:

public void countKeyWords(File file) throws IOException {

        BufferedReader input = new BufferedReader(new FileReader(file));

        String line = null;

        while ((line = input.readLine()) != null) {

            line = line.trim();

            if (line.startsWith("//")) continue; //不处理单行注释

            else if (line.contains("/*")) { //多行,文档与尾行注释

                if (!line.startsWith("/*")) matchKeywords(line);//第一行算代码,其余注释

                while (!line.endsWith("*/")) {

                    line = input.readLine().trim();

                }

            }

            matchKeywords(line); //对代码行进行统计

        }

    }

(4)输出结果。

 

小结:

写这道题之前,重新又温习了一遍正则表达式的网课,所以在正则表达式上没有大的问题,并且,在每次写正则表达式的时候,我都会使用正则表达式测试网站验证自己的正则表达式,效率和正确率都有所提高。

 4.日期问题面向对象设计(聚合二)(题目集5

聚合二相较聚合一,PTA通过标准更加严苛。代码长度限制有所缩短,提交代码时,代码如果有使用了两个if嵌套,运行大多会超时,那个测试点会不通过。其中有个下n天的测试点我一直没能通过,将N1的类型由int改为long就可以通过。

case 1:

                int year1 = Integer.parseInt(in.next());

                int month1 = Integer.parseInt(in.next());

                int day1 = Integer.parseInt(in.next());

                long N1 = in.nextInt();

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

                if (!day01.checkInputValidity()) {

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

                } else

                    System.out.println(year1 + "-" + month1 + "-" + day1 + " next " + N1 + " days is:" + day01.getNextNDays(N1).showDate());

                break;

 

Main类结构:

 

 

 


5.图形继承与多态(题目集
6
 

这道题考察点主要在于深入理解继承与多态的原理及用法还有ArrayList,List等的使用。

为不同的图形创建不同的类,在类中创建计算面积的方法。并将每个图形的面积存入list数组中,一系列输出后。因为listArrayList型的,所以可以使用Collection

工具类将其进行排序:Collections.sort(list);

for(double o:list)

 System.out.print(String.format("%.2f",o)+" ");

再将list集合遍历赋值给o并输出。

Shape被定义为抽象类,声明为abstract成员可以不包括实现代码,但只要类中还有未实现的抽象成员(抽象方法),那么这个类就是一个抽象类,抽象类的对象不能被实例化,通常作为被强制继承类必须实现某一成员,抽象类必须要有派生子类。并且,如果子类没有实现抽象类的所有方法,则子类也成为一个抽象类。

作为修饰符,abstract声明了一种没有具体对象的,出于组织概念的层次关系需要而存在的抽象类;作为类方法修饰符,abstract则声明了一种仅有方法头,而没有具体操作实现的方法体的抽象方法。

eg.

abstract class  Shape{

public abstract double getArea();

public abstract boolean validate();

public abstract String toString();

}

可见,abstract方法只有方法头的声明,而用一个分号代替方法体的定义;至于方法体的具体实现。那是由当前类的不同子类在他们各自的类定义中完成的。

 

Main类结构:

 

 6.实现图形接口及多态性(题目集6

这道题考察的是最近学习的实现类的封装性、继承性和多态性。

这是第一次,比较正式的使用接口来写代码。

我在做题后再一次详细整理了接口的一些使用,如下:

(1)声明格式:

使用interface修饰,是一种引用数据类型。

eg.

[访问修饰符] interface接口名 [extends 父接口1,父接口2...]{

常量定义;

方法定义;

}

(2)定义接口说明:

如果一个类中所有的方法均为abstract方法,那么这个类就可以声明为接口。

eg.

源码:

public abstract class MyAbstract{

public abstract void method01();

public abstract void method02();

public abstract void method03();

}

改正后:

public interface MyInterface{

//方法:public abstract void method01();//public abstract可以省略

void method01;

void method02;

void method03;

}

①常量:接口中的属性只能是常量,总是:public static final修饰。不写也是。

②方法:接口中的方法只能是:publci abstract。省略的话,也是public abstract

③接口不能实例化:接口中不允许出现构造方法。因为接口不是类。

④新特性:使用static来定义静态方法,使用default来定义普通方法。

⑤接口的继承性(传递性):接口完全支持多继承。和类的继承类似,子接口扩展某个父接口,将会获得父接口中所定义的一切。

(3)接口与类的关系:

①子类通过implements来实现接口中的规范。

②一个类既存在继承关系,又存在实现关系时:extends在前,implements在后。

③如果父类与接口有完全相同的方法,子类/实现类所实现的方法是父类的方法(父类优先于接口)。

④如果父类中与接口中有同名方法时,父类与接口中的方法,在子类/实现类中构成方法的重载。

⑤一个类可以同时实现多个接口。

 

 

 

该题使用了接口的部分代码如下:

class Circle implements GetArea{

    private double radius;

    public Circle(){}

    public Circle(double radius){

        this.radius = radius;

    }

 

    public void setRadius(double radius) {

        this.radius = radius;

    }

 

    public double getRadius() {

        return radius;

    }

    public double getArea(){

        return Math.PI * radius * 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;

    }

 

    public void setWidth(double width) {

        this.width = width;

    }

 

    public double getWidth() {

        return width;

    }

 

    public void setLength(double length) {

        this.length = length;

    }

 

    public double getLength() {

        return length;

    }

    public double getArea(){

        return width * length;

    }

}

 

Main类结构:

 

 

 


  

三、总结与心得

1.目前好像只是接触了类设计的单一原则,对该原则的理解是不能跑题,方法必须围绕着类进行。取类名要做到见名知义,属性是分量。

2.通过测试,能够检测编码的质量好坏。

3.明确知晓了类设计的额单一职责原则:类里面的变量的属性一般为私有属性。

4.了解了类和类的四种关系:耦合(关联,聚合,依赖,泛化)且耦合度要越低越好,内聚等的概念;类的封装性:private,public,protected,默认的(都可以不写);类的继承性:可复用性(父类parent class,超类super class,基类base class,子类son class,派生类derived class,及构造方法链的知识点);类的多态性:不同的对象,接收到同一个消息的时候,执行不同的操作。

5.语法依旧还不熟练,导致很多时候在写代码的时候因为某些语法问题卡住或者报错。

6.依然保持着做题前,简单的画一个大致思路的草图,在思路上有明确的方向,只是有很多知识点依然不会,所以就算思路有,很多时候却不好实现。