Blog3

一、前言

  通过一个学期的学习,我们终于结束了面向对象程序设计这门课,在过去的几周时间内,我们进行了实验、pta以及最后的期末考试,课程虽然结束了,但需要学习和巩固的知识点还有很多,这也是最后一次blog总结。

 

二、设计与分析

1.电信计费问题

题目要求:

实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
南昌市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。

类图如下:

 

  SourceMonitor报表:

 

部分代码:

class User {
    private UserRecords userRecords = new UserRecords();
    private double balance = 100;
    private ChargeMode chargeMode;
    private String number;

    public void calBalance() {
        balance = balance - calCost() - chargeMode.getMonthlyRent();
    }

    public double calCost() {
        return chargeMode.calCost(userRecords) ;
    }

    public UserRecords getUserRecords() {
        return userRecords;
    }

    public void setUserRecords(UserRecords userRecords) {
        this.userRecords = userRecords;
    }

    public double getBalance() {
        return balance;
    }


    public ChargeMode getChargeMode() {
        return chargeMode;
    }

    public void setChargeMode(ChargeMode chargeMode) {
        this.chargeMode = chargeMode;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
}

 

class LandPhoneInLandRule extends CallChargeRule{
    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        long interval;
        double cost = 0;
        for(int i = 0; i < callRecords.size(); i++){
            interval = callRecords.get(i).getEndTime().getTime() - callRecords.get(i).getStartTime().getTime();
            if(interval % 60000 == 0){
                interval = interval / 60000;
            } else {
                interval = interval / 60000 +1;
            }
            cost = cost + interval*0.6;
        }
        return cost;
    }
}


class LandPhoneInCityRule extends CallChargeRule{


    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        long interval;
        double cost = 0;
        for(int i = 0; i < callRecords.size(); i++){
            interval = callRecords.get(i).getEndTime().getTime() - callRecords.get(i).getStartTime().getTime();
            if(interval % 60000 == 0){
                interval = interval / 60000;
            } else {
                interval = interval / 60000 +1;
            }
            cost = cost + interval*0.1;
        }
        return cost;
    }
}

这次的电信计费问题是我认为难度最大的一道题,它是对我们java整体知识框架的考察,实话实说,我并没有把这道题目做出来,可能是因为我对知识和题目的处理还不太熟悉和细致,面对这种复杂的题目,不知道从哪里下手。

 

题目2:

题目要求:

定义容器Container接口。模拟实现一个容器类层次结构,并进行接口的实现、抽象方法重写和多态机制测试。各容器类实现求表面积、体积的方法。

定义接口Container:
属性:
public static final double pi=3.1415926;
抽象方法:
public abstract double area();
public abstract double volume();
static double sumofArea(Container c[]);
static double sumofVolume(Container c[]);
其中两个静态方法分别计算返回容器数组中所有对象的面积之和、周长之和;

定义Cube类、Cylinder类均实现自Container接口。

Cube类(属性:边长double类型)、Cylinder类(属性:底圆半径、高,double类型)

实验代码:

import java.util.Scanner;
public class Main {
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int n=in.nextInt();
        Container[] c = new Container[n];
        for(int i = 0;i < n;i++) {
            String s = in.next();
            if(s.equals("cube")) {
                double d = in.nextDouble();
                c[i] =  new Cube(d);
            }
            else if(s.equals("cylinder")) {
                double r = in.nextDouble();
                double h = in.nextDouble();
                c[i] = new Cylinder(r,h);
            }
        }
        System.out.printf("%.2f\n%.2f",Container.sumOfArea(c),Container.sumOfVolume(c));
        in.close();
    }
}
interface Container {
    double pi = 3.1415926;
    double area();
    double volume();

    static double sumOfArea(Container[] c) {
        double sum = 0;
        for (int i = 0; i < c.length; i++) {
            sum += c[i].area();
        }
        return sum;
    }

    static double sumOfVolume(Container[] c) {
        double result = 0;
        for (int i = 0; i < c.length; i++) {
            result += c[i].volume();
        }
        return result;
    }
}
class Cube implements Container{
    public double d;
    public Cube(double d2) {
        this.d = d2;
    }
    public double area() {
        return 6*d*d;
    }
    public double volume() {
        return Math.pow(d, 3);
    }


}
class Cylinder implements Container{
    public double r,h;
    public Cylinder(double r2, double h2) {
        this.r = r2;
        this.h = h2;
    }
    public double area() {
        return (2*pi*r*h + 2*pi*r*r);
    }
    public double volume() {
        return (pi*r*r*h);
    }
}

这道题目比较简单,就是普通的接口问题,Cube类、Cylinder类均要实现自Container接口,抽象方法分别计算返回容器数组中所有对象的面积之和、周长之和,方法比较简单,只要知道接口的原理再按照题目提示把代码写出即可。

 

题目3:

题目要求:

现在他要统计班里学生的名单,但是C~K在教务系统中导出班级名单时出了问题,发现会有同学的信息重复,现在他想把重复的同学信息删掉,只保留一个。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        List<Student> List=new ArrayList<Student>();
        
        int n=in.nextInt();
        for(int i=0;i<n;i++)
        {
            String number = in.next();
            String name = in.next();
            int age = in.nextInt();
            char sex = in.next().charAt(0);
            Student stu=new Student(number,name,age,sex);
            if(!List.contains(stu))
            {
                List.add(stu);
            }
        }
        Collections.sort(List);
        System.out.println(List.size());
        Iterator<Student> a = List.iterator();
        while(a.hasNext())
        {
            Student next = a.next();
            System.out.println(next);
        }
        in.close();
    }
}

class Student implements Comparable<Student>{
    String idString;
    String nameString;
    int ageString;
    char sexString;
    public Student(String idString, String nameString, int ageString, char sexString) {
        super();
        this.idString = idString;
        this.nameString = nameString;
        this.ageString = ageString;
        this.sexString = sexString;
    }
    
    public int hashCode() {
        final int p = 31;
        int r = 1;
        r = p * r + ageString;
        r = p * r + ((idString == null) ? 0 : idString.hashCode());
        r = p * r + ((nameString == null) ? 0 : nameString.hashCode());
        r = p* r + sexString;
        return r;
    }
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (ageString != other.ageString)
            return false;
        if (idString == null) {
            if (other.idString != null)
                return false;
        } else if (!idString.equals(other.idString))
            return false;
        if (nameString == null) {
            if (other.nameString != null)
                return false;
        } else if (!nameString.equals(other.nameString))
            return false;
        if (sexString != other.sexString)
            return false;
        return true;
    }
    public String toString() {
        return  idString + " " + nameString + " " + ageString + " " + sexString ;
    }
    public int compareTo(Student o) {
        return this.idString.compareTo(o.idString);
    }
}

这道题使用了arraylist 等有关列表的方法,题目本身不难,只要小心把每种情况计算进去就行,题目解法也不唯一,可以尝试用多种方法解决该问题。

 

期末考试:

代码:

import java.util.Scanner;
import static java.lang.Math.PI;
public class qimo {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int choice = 0;
        choice = in.nextInt();
        switch (choice) {
            case 1://Construct Circle Object
                double a = in.nextDouble();
                if(a<=0){
                    System.out.println("Wrong Format");
                    return;
                }
                else {
                    Circle circle = new Circle(a);
                    circle.show();
                    break;
                }
            case 2://Construct Rectangle Object
                double b = in.nextDouble();
                double c = in.nextDouble();
                if(b<=0||c<=0){
                    System.out.println("Wrong Format");
                    return;
                }
                else{
                    Rectangle rectangle = new Rectangle(b,c);
                    rectangle.show();
                    break;
                }

            case 3://Construct Ball Object
                double d = in.nextDouble();
                if(d<=0){
                    System.out.println("Wrong Format");
                    return;
                }
                else{
                    Ball ball = new Ball(d);
                    ball.show();
                    break;
                }

            case 4://Construct Box Object
                double f = in.nextDouble();
                double g = in.nextDouble();
                double h = in.nextDouble();
                if(f<=0||g<=0||h<=0){
                    System.out.println("Wrong Format");
                    return;
                }
                else{
                    Box box = new Box(f,g,h);
                    box.show();
                    break;
                }

            default:
                System.out.println("Wrong Format");
                break;
        }
    }

}
abstract class AbstractShape{
    abstract public double getArea();
    abstract public void show();
}
class Circle extends AbstractShape{
    private double radius;
    public Circle() {
    }
    public Circle(double radius) {
        this.radius = radius;
    }
    public double getArea() {
        double area;
        area = PI*radius*radius;
        return area;
    }
    public void show() {
        System.out.println("Type:Circle,Area:"+String.format("%.2f",getArea()));
    }
    public double getRadius() {
        return radius;
    }
    public void setRadius(double radius) {
        this.radius = radius;
    }
}
class Rectangle extends AbstractShape{
    private double width;
    private double length;
    public Rectangle(){

    }
    public Rectangle(double width,double length) {
        this.width = width;
        this.length = length;
    }

    public double getArea() {
        double area;
        area = width*length;
        return area;
    }

    public void show() {
        System.out.println("Type:Rectangle,Area:"+String.format("%.2f",getArea()));
    }

    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;
    }
}
class Box extends Rectangle{
    private double height;
    public Box() {

    }
    public Box(double width,double length,double height) {
        this.setWidth(width);
        this.setLength(length);
        this.setHeight(height);
    }
    public double getHeight() {
        return height;
    }
    public void setHeight(double height) {
        this.height = height;
    }
    public double getArea() {
        double area;
        area = 2*(getWidth()*getLength()+getWidth()*getHeight()+getLength()*getHeight());
        return area;
    }
    public void show(){
        System.out.println("Type:Box,Area:"+String.format("%.2f",getArea()));
    }
}
class Ball extends Circle{
    public Ball(){

    }
    public Ball(double radius){
        this.setRadius(radius);
    }
    public double getArea() {
        double area;
        area = 4*PI*getRadius()*getRadius();
        return area;
    }
    public void show(){
        System.out.println("Type:Ball,Area:"+String.format("%.2f",getArea()));
    }
}

 

本次期末考试我只写出了第一题,但是是最后几分钟才想到引用Math里的PI,之前直接用3.14表示Π导致测试点一直通不过,题目本身不难,和期中考试的题目有点类似,不过是继承了两次,但大致的方法还是相同的,保留两位小数需要使用

String.format("%.2f",getArea())

 

三、踩坑心得

 

1.对于全局变量和局部变量需要格外注意,不然容易导致结果出错。全局变量就是从定义的位置起,作用域覆盖整个程序范围的变量。而只在特定的过程或函数中可以访问的变量,被称为局部变量。

2.处理父类和子类关系时,要了解继承的关系和逻辑,不然得出的答案可能会出错。

3.处理类里的变量时,因为属性是私有的,所以调用时只能用get()方法处理。

4.处理问题中的计算问题不能想当然,像这次期末考试的Π不能直接用3.14代。

 

四、改进建议

 

1.在代码中多标明注释,以便理解和下次修改。

2.有些代码中有一部分功能相同,可以改成方法,使代码更加简洁,也便于下次对代码进行修改。

3.有一些类也可以和其他类一样变成父类的子类,应该尽量减少代码的重复率,提高代码的利用率和可读性。

4.可以尝试使用不同的方法解决同一道题。

 

五、总结

       经过一个学期的JAVA课程学习,现在虽说算不上什么专业的JAVA程序员,但我还是很有收获。了解了这门语言,探索了这门语言,认知了这门语言。我从一个什么都不懂的菜鸟,到现在能够自己编一个简单的程序并使其跑起来,学习JAVA应该是循环渐进,按部就班,脚踏实地的。学JAVA,一定要做到课前预习与课后复习,书上的概念要理解透彻,代码一定要过手;多和同学沟通,互相学习,取长补短。我觉得应该多看别人的总结,多与别人进行交流,但是本学期学习压力较大,可能自己也不是学的很好,我对课程提出的建议就是我认为pta上的题目可以中档难度的题目多一些,而不是太难的题目,这不仅会使我们学习的自信下降,等下一次pta发布又是这道难题的升级版,无从下手,最终陷入恶性循环。其次,我觉得提交的时间应该更加人性化一点,多给些时间也能让学生们的学习压力减轻一些,不会感觉那么压迫,丧失对java学习的兴趣。Java基础课程已经结束,但对于Java知识的学习与提升才刚刚开始。更熟练的使用Java,更好的类关系设计将作为之后学习的目标与方向。相较于Java宏大的知识体系,所学的知识不过风毛菱角,更加丰富的知识还尚未来到。要不断学习,不断探索,虚心学习,勤于练习。 

posted on 2022-06-18 21:35  xrhmxyrs  阅读(105)  评论(0)    收藏  举报