第三次Blog作业——对本门课程的总结

前言

在本学期面向对象程序设计的学习过程中,完成许多任务了:

  • PTA作业:前三次题目集主要是对程序设计基础知识的回顾。到第四次题目集,接触到类的概念并开始了我人生中第一次类设计。从第五次到第七次题目集是对单部电梯调度程序的设计和迭代,第八次和第九次题目集是对航空货运管理系统的设计和迭代。最后两次题目集则是到了集合框架和期末复习。
  • Blog作业:分别是对PTA作业中的程序设计与迭代的总结,和本次作业对整门课程的总结。
  • 实验:实验一主要是Java环境的安装和测试,实验二到四是对大象装冰箱程序的不断迭代和设计,实验五是使用JavaFX技术为大象装冰箱程序引入图形界面。
  • 线上课程以及线下课程:对使用Java进行面向对象程序设计的知识进行讲解。

面向对象技术总结

一、封装

核心思想:将数据与操作数据的方法绑定在一起,隐藏内部实现细节,仅暴露必要的接口。

实现方式:

访问修饰符:
  • private:仅当前类可见(最严格的封装)。
  • public:全项目可见。
  • protected:同包或子类可见。
  • 默认(无修饰符):同包可见。
getter/setter 方法:

通过公共方法访问和修改私有属性。

点击查看代码
class Point
{
    private double x;
    private double y;

    public Point()
    {
        x = 0;
        y = 0;
    }

    public Point(double x, double y)
    {
        this.x = x;
        this.y = y;
    }

    public double getX()
    {
        return x;
    }

    public void setX(double x)
    {
        this.x = x;
    }

    public double getY()
    {
        return y;
    }

    public void setY(double y)
    {
        this.y = y;
    }

    public void dispaly()
    {
        System.out.printf("(%.2f,%.2f)\n" , x, y);
    }

}
来自实验七:点与线

二、继承

核心思想:子类继承父类的属性和方法,实现代码复用。

关键特性:

关键字:extends(Java 只支持单继承)。
构造函数调用:子类构造函数默认调用父类无参构造(super())。
方法重写(Override):子类可覆盖父类方法,需满足:
  • 方法名、参数列表、返回类型完全一致。
  • 访问修饰符不能比父类更严格。
super 关键字:访问父类的属性或方法。
点击查看代码
class Lion extends Animal
{
    public Lion(String name, int weight, int height)
    {
        super(name, weight, height);
    }

    @Override
    public void cry()
    {
        System.out.println(getName() + ":怒吼一声");
    }

    @Override
    public int getAttackPower()
    {
        return 1;
    }
}
来自实验四
继承是 “is-a” 关系(如 Dog is-a Animal)。
父类的private成员无法被继承。

三、多态

核心思想:同一操作作用于不同对象,产生不同的执行结果。

两种形式:

编译时多态(静态多态):

通过方法重载(Overload)实现。
  • 要求:方法名相同,参数列表不同(类型 / 顺序 / 数量)。

运行时多态(动态多态):
  • 通过方法重写和父类引用指向子类对象实现。
点击查看代码
Animal animal = new Lion();  // 父类引用指向子类对象
animal.cry();  // 调用Lion的cry()方法(动态绑定)
来自实验四
优势:
  • 提高代码扩展性(如新增子类无需修改调用方代码)。
  • 实现接口复用,降低耦合度。

四、抽象类

定义:

包含abstract关键字的类,不能直接实例化。

特点:

  • 可包含抽象方法(无方法体,需子类实现)和普通方法。
  • 子类必须实现所有抽象方法(除非子类也是抽象类)。
点击查看代码
abstract class Cargo implements Ratable
{
    private int id;
    private String name;

    private double length;
    private double width;
    private double height;

    private double grossWeight;

    public Cargo()
    {
    }

    public Cargo(int id, String name, double length, double width, double height, double grossWeight)
    {
        this.id = id;
        this.name = name;
        this.length = length;
        this.width = width;
        this.height = height;
        this.grossWeight = grossWeight;
    }

    public int getId()
    {
        return id;
    }

    public void setId(int id)
    {
        this.id = id;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

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

    public double getHeight()
    {
        return height;
    }

    public void setHeight(double height)
    {
        this.height = height;
    }

    public double getGrossWeight()
    {
        return grossWeight;
    }

    public void setGrossWeight(double grossWeight)
    {
        this.grossWeight = grossWeight;
    }

    public double getVolumeWeight()
    {
        return length * width * height / 6000;
    }

    public double getFeeWeight()
    {
        return Math.max(grossWeight, getVolumeWeight());
    }

    public double getCost()
    {
        return getFeeWeight() * getRate();
    }
}

class NormalCargo extends Cargo
{
    public NormalCargo()
    {
    }

    public NormalCargo(int id, String name, double length, double width, double height, double grossWeight)
    {
        super(id, name, length, width, height, grossWeight);
    }

    @Override
    public double getRate()
    {
        if (getFeeWeight() < 20)
        {
            return 35;
        }
        else if (getFeeWeight() < 50)
        {
            return 30;
        }
        else if (getFeeWeight() < 100)
        {
            return 25;
        }
        else
        {
            return 15;
        }
    }
}
来自题目集九:航空货运管理系统

五、接口

定义:

使用interface关键字,本质是特殊的抽象类(全是抽象方法)。

特点:

  • 接口中的属性默认是public static final。
  • 子类用implements实现接口,需实现所有抽象方法。
点击查看代码
interface Ratable
{
    double getRate();
}
来自题目集九:航空货运管理系统

六、集合框架

核心架构:以java.util包为核心,分为Collection和Map两大体系。

1. Collection 体系(存储单个元素)

List 接口:有序、可重复,实现类包括:
  • ArrayList:基于数组,随机访问快,增删慢。
  • LinkedList:基于链表,增删快,随机访问慢。
  • Vector:线程安全(已过时,推荐CopyOnWriteArrayList)。
Set 接口:无序、不可重复,实现类包括:
  • HashSet:基于哈希表,查询快,插入顺序不保留。
  • TreeSet:基于红黑树,元素有序(需实现Comparable)。
  • LinkedHashSet:保留插入顺序,结合哈希表和链表。
  • Queue 接口:队列(先进先出),实现类如LinkedList、PriorityQueue。

2. Map 体系(存储键值对)

  • HashMap:基于哈希表,查询和修改效率高(非线程安全)。
  • TreeMap:基于红黑树,键有序(需实现Comparable)。
  • ConcurrentHashMap:线程安全的高效 Map(Java 8 后用分段锁优化)。
  • Hashtable:线程安全(已过时,不推荐)。

常用操作:

  • 遍历:for-each、迭代器(Iterator)、Lambda 表达式(Java 8+)。
  • 泛型:List、Map<Integer, Object>,避免类型转换异常。

七、异常

异常是程序运行时的错误,Java 通过try-catch-finally和throws机制处理。

异常分类:

  • Checked Exception:必须显式处理(如IOException)
  • Unchecked Exception:继承自RuntimeException(如NullPointerException)
  • Error:系统级错误(如OutOfMemoryError)
点击查看代码
    public static void savePaid(OrderManager orderManager)
    {
        try (FileWriter writer = new FileWriter("order_manager.txt", true))
        {
            writer.write(orderManager.toString());
            writer.write(System.lineSeparator());
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
来自JavaFX作业

八、JavaFX

核心组件:

  • 控件:Button、TextField、TableView、Chart等。
  • 布局:BorderPane、HBox、VBox、GridPane。
  • 事件处理:Lambda 表达式或匿名内部类(如button.setOnAction(e -> System.out.println("Clicked")))。
点击查看代码
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Main extends Application
{

    public static void main(String[] args)
    {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage)
    {
        primaryStage.setTitle("JavaFX Slider 功能演示");
        BorderPane root = new BorderPane();
        root.setPadding(new Insets(20));

        // 创建顶部标题
        Text title = new Text("JavaFX Slider 功能演示");
        title.setFont(Font.font("Arial", 24));
        title.setFill(Color.DARKBLUE);
        HBox titleBox = new HBox(title);
        titleBox.setPadding(new Insets(0, 0, 20, 0));
        titleBox.setAlignment(javafx.geometry.Pos.CENTER);
        root.setTop(titleBox);

        // 创建滑块演示区域
        VBox sliderDemoBox = new VBox(20);
        sliderDemoBox.setPadding(new Insets(20));
        sliderDemoBox.setBorder(new Border(new BorderStroke(Color.LIGHTGRAY, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));

        // 水平滑块
        Label basicSliderLabel = new Label("水平滑块:");
        Slider basicSlider = new Slider(0, 100, 50);

//        basicSlider.setShowTickLabels(true); // 显示刻度
//        basicSlider.setShowTickMarks(true); // 显示刻度线
//        basicSlider.setMajorTickUnit(20); // 设置主刻度间隔
//        basicSlider.setMinorTickCount(4); // 设置每个主刻度间的小刻度数量

        Label basicSliderValueLabel = new Label("当前值: " + basicSlider.getValue());
//         观察者模式获取Slider的值
//        basicSlider.valueProperty().addListener((observable, oldValue, newValue) ->
//        {
//            basicSliderValueLabel.setText("当前值: " + String.format("%.1f", newValue.doubleValue()));
//        });

        VBox basicSliderBox = new VBox(10, basicSliderLabel, basicSlider, basicSliderValueLabel);

        // 垂直滑块
        Label verticalSliderLabel = new Label("垂直滑块:");
        Slider verticalSlider = new Slider(0, 30, 15);
//        verticalSlider.setOrientation(Orientation.VERTICAL); // 设置为垂直滑块,默认值为HORIZONTAL

//                verticalSlider.setShowTickLabels(true); // 显示刻度
//                verticalSlider.setShowTickMarks(true); // 显示刻度线
//                verticalSlider.setMajorTickUnit(10); // 设置主刻度间隔
//                verticalSlider.setMinorTickCount(1); // 设置每个主刻度间的小刻度数量

        HBox verticalSliderBox = new HBox(20, verticalSliderLabel, verticalSlider);
        verticalSliderBox.setAlignment(javafx.geometry.Pos.CENTER_LEFT);

        // 添加所有滑块演示到主区域
        sliderDemoBox.getChildren().addAll(basicSliderBox, verticalSliderBox);
        root.setCenter(sliderDemoBox);
        Scene scene = new Scene(root, 600, 800);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}
翻转课堂的示例

踩坑心得

一、冷静和耐心

写PTA熬到深夜,代码始终跑不通。

这不是我一个人的经历,许多同学也有共同的体验。究其原因,不仅仅是审题和题目难度的问题,还有在一次又一次的失败面前红温,最终失去耐心,进行着没有意义的尝试。面对难题,清醒的头脑和百折不挠的耐心是很重要的品质。

二、合理的设计

对于一个需要不断迭代的项目来说,一个合理的设计非常重要。
在我一开始设计类的时候,这一点就做的非常不好。比如单部电梯调度程序,根本就没有设计,先写代码,然后拿着代码生成类图,结果生成了一团蜘蛛网

这对于后续的迭代造成了极大的困难。

改进建议及总结

建议

  1. 希望提交实验不要手敲代码,这真的太折磨了。虽然代码可以复制上一次的实验,但是实验提交系统的用户体验实在是太糟糕了,没有ide的自动补全和错误提示也就算了,甚至连显示空白字符的功能也没有。不仅如此,在这个实验提交系统上打字也很不舒服,用起来还不如记事本。
  2. 希望线上课程的作业部分的答案能够合理一些,比如答案是"final"和"static",输入是"static"和"final",还有答案是"super()";,输入是"super()"。这种情况都能被判错误。
  3. 希望实验指导书的内容能够具体一些,有的地方指导书要求实现每个功能,但这个功能应该用在什么地方却没有提及,经常搞得人一头雾水。

总结

本学期的面向对象程序设计学习,是从基础语法到复杂系统设计的全面进阶。从最初通过 PTA 题目集回顾 Java 基础,到逐步接触类设计、电梯调度与航空货运系统的迭代开发,每一次作业和实验都推动着对封装、继承、多态等核心思想的理解从理论走向实践。印象最深的是在单部电梯调度程序中,因初期类设计不合理导致的代码混乱,让我深刻认识到面向对象设计中 “高内聚、低耦合” 的重要性;而 JavaFX 图形界面的开发,则让我体会到面向对象思想在跨领域应用中的灵活性。
实验与 Blog 作业的结合,帮助我将碎片化的知识系统化 —— 从大象装冰箱程序的迭代到航空货运系统的架构设计,每一次总结都伴随着对代码逻辑的重新审视。尽管在 PTA 作业中多次因细节错误熬夜调试,也在实验提交系统中遇到过操作不便的问题,但这些挑战反而强化了查错能力和耐心。如今再回顾最初生成的 “蜘蛛网” 类图,更能感受到从 “面向过程” 到 “面向对象” 思维转变的价值。这门课程不仅夯实了 Java 编程基础,更培养了我用系统化思维解决复杂问题的能力,为后续软件开发学习奠定了坚实基础。

posted @ 2025-06-22 21:49  存默  阅读(10)  评论(0)    收藏  举报