面向对象程序设计课程总结BLOG
面向对象程序设计(JAVA)课程全面总结
前言:课程学习全景回顾
本学期的面向对象程序设计(JAVA)课程给我带来了丰富的学习体验和编程实践机会。本课程分为PTA作业、BLOG总结、实验项目、线上学堂在线视频学习和线下课堂讲解,这些线上线下、理论实践结合的方式让我对Java语言和面向对象编程思想有了系统性的认识。
PTA从题目集1的基础语法练习开始,到题目集11的综合系统设计,呈现明显的循序渐进特点。早期题目如"圆柱体体积计算"、"温度转换"等问题,暂时还没有体现面向对象的特征,是为了巩固回忆之前的编程基础;中期题目如"判断三角形类型"、"检查ISBN-10"让我开始接触初步的面向对象特征;最后的题目集7到11的Blog作业,例如"图形卡片排序游戏"、"航空货运管理系统",则是全面考察面向对象设计能力,“模拟电梯调度”更是考察了我们对题目的理解能力和类设计的能力,对于当时初步门槛的我们造成了不小的挑战。这些题目集促使我不断反思和总结学习过程,这种"做中学、学中思"的方式效果显著。
实验部分从简单的"大象放进冰箱"程序开始,逐步扩展到多种动物和电器的管理,最终实现图形界面,这个渐进过程对于我们学习面向对象编程也是很好的实践。
线上课程视频内容系统全面,可以反复观看难点部分,并且每一节都有附带练习,可以加强巩固;
线下课堂则主要通过实例演示,让我们在实际情况中加深理解。
总体而言,课程内容丰富充实,理论与实践结合紧密。虽然后期作业和实验的工作量较大,需要投入较多时间,但正是这种在适度的压力下我们才不至于停滞不前,才能不断突破自我,获得实实在在的编程能力提升。
面向对象技术掌握情况
封装:面向对象的基础
封装是面向对象编程的基础,通过将数据和行为捆绑在一起,并控制对内部的访问权限,我学会了如何构建更安全、更易维护的代码。例如,在PTA题目集5的"单部电梯调度程序"中,我第一次尝试了封装。在以后的编程实践中,封装已经成了家常便饭,以下是封装的主要实现:
- 将类的属性设为private,通过get和set方法提供访问
- 在方法中添加参数校验,防止非法数据
- 将相关操作组织在同一个类中,提高内聚性
代码示例
class Person {
private String name;//将name变量设置为private
public void setName(String name) { //set方法
this.name = name;
}
public String getName() { //get方法
return name;
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person();
person.setName("小明"); // 使用set方法设置名字
System.out.println(person.getName()); // 使用get方法获取名字打印
}
}
封装通过隐藏实现细节,提高了代码的复用性和安全性,使对象的内部实现和外部接口可以相互独立,也提高可维护性,通过多次练习,我现在已经养成了"先思考访问权限"的习惯,不再随意使用public修饰所有成员。
继承:面向对象编程技术的基石
继承是java面向对象编程技术的一块基石,它允许子类继承父类的特征和行为,使得子类对象(实例)具有父类的特征,子类还可以从父类继承方法,使得子类具有父类相同的行为。继承使用“extends”关键字进行声明,例如可以创建一个“Student”子类,继承自“Person”:
class Person {
protected String name; // 改为protected以便子类直接访问
public void setName(String name) { this.name = name; }
}
class Student extends Person {
private String studentId; // 子类特有字段
// 子类自动拥有父类的setName方法
}
此时Student类会拥有Person的name字段和setName()方法,同时可以扩展独有的字段(如学号),也就是说子类是父类的扩展,不可认为子类就是父类的子集。
我学到的关键经验:
- 继承关系必须真实反映"是一种"的逻辑关系,就比如“学生(Student)”属于“人(Person)”,不能仅仅为了复用代码而强行继承
- 父类应当足够抽象,包含真正通用的属性和行为
- 子类扩展时要注意保持父类的基本行为特征
- 当继承层次超过3层时,就需要考虑是否应该重构
super关键字的使用曾让我困惑,特别是在多层继承和构造函数调用时,很容易让人搞混。通过反复调试题目集9的代码,我终于掌握了super的正确用法:在子类构造器中,super()必须放在第一行;在重写方法中,可以通过super.method()调用父类实现。
多态:灵活编程的有效手段
多态是我觉得最神奇的面向对象特性。它允许我们用父类类型统一处理不同子类对象,使代码更灵活、可扩展。还是继续拿上面的例子,我们可以在子类中对父类的方法进行重写:
class Person {
void introduce() {
System.out.println("我是一个普通人。");
}
}
class Student extends Person {
@Override
void introduce() {
System.out.println("我是一名学生。");
}
}
class Teacher extends Person {
@Override
void introduce() {
System.out.println("我是一名老师。");
}
}
然后在实际编程中,我们可以利用多态的特性编写更加通用的代码。比如创建一个方法来统一处理所有Person类型对象的“介绍”(introduce):
public class Main {
public static void main(String[] args) {
// 1. 向上转型(父类引用指向子类对象)
Person person1 = new Student();
Person person2 = new Teacher();
person1.introduce(); // 输出:"我是一名学生。"
person2.introduce(); // 输出:"我是一名老师。"
}
}
我理解的多态要点:
- 通过方法重写(Override)实现运行时多态
- 父类引用可以指向子类对象(向上转型)
- 使用instanceof检查和强制转换可以实现向下转型
- 接口也是实现多态的重要方式
在实验的"动物管理"程序中,我通过让不同动物实现相同的makeSound()接口,实现了统一管理不同动物的叫声,这是多态的典型应用场景。
抽象类与接口
Java中,接口和抽象类的分别由interface与abstract关键字来定义。抽象类和接口是课程中的重要内容,需要通过对比学习理解了它们的异同:
抽象类:
- 可以包含抽象方法和具体实现
- 用于表示"是什么"的本质
- 适合作为相关类的共同基类
- 子类通过extends继承
接口:
- 只定义方法签名(Java 8后可以有默认方法)
- 用于表示"能做什么"的能力
- 适合描述跨继承树的功能
- 类通过implements实现
在题目集10的"图形卡片游戏"中,我最初混淆了两者的使用,将本应作为接口的绘图功能放到了抽象类中,导致后期扩展困难。通过重构,我学会了合理划分抽象类和接口的职责。
集合框架
Java集合框架大大简化了数据处理工作。通过PTA题目如"谷仓容积排序"和"关键词统计",我接触了:
- List接口及其实现类ArrayList/LinkedList的特性和使用场景
- Set接口和HashSet/TreeSet的去重特性
- Map接口和HashMap/TreeMap的键值对管理
- Collections工具类的排序、查找等方法
- 泛型在集合中的应用,确保类型安全
在"关键词统计"题目中,我最初使用ArrayList频繁查找导致性能低下,后来发现可以改用HashSet快速判断关键词是否存在,这样实现的话效率提升明显。
异常处理
异常处理是构建健壮程序的关键。最初,我只是简单地在main方法抛出所有异常,后来学习了try-catch和throw,能够更精准地捕获和处理异常,使程序更加稳定和可维护。
- try-catch:捕获并处理异常
try {
// 可能抛出异常的代码
FileInputStream fis = new FileInputStream("data.txt");
int data = fis.read();
catch (FileNotFoundException e) {
System.err.println("文件未找到:" + e.getMessage());
catch (IOException e) {
System.err.println("IO错误:" + e.getMessage());
finally {
System.out.println("无论是否异常,都会执行");
- try:包裹可能抛出异常的代码
- catch:捕获特定异常并处理
- finally:无论是否发生异常,都会执行(常用于资源释放)
- throw:主动抛出异常
public void checkAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
System.out.println("年龄合法:" + age);
throw 用于在代码中主动抛出异常(如参数校验失败时)
良好的异常处理能让程序更健壮,减少崩溃风险,同时提升代码的可读性和可维护性。
JavaFX:图形界面开发的初体验
JavaFX是我课程中相对薄弱的部分。虽然完成了"大象冰箱"实验的图形界面,但仅停留在基础组件使用层面,也临时学了不少。我掌握了:
- 基本的布局(HBOX、VBOX等)和各种形状(Ciecle、Rectangle等)的构建
- 控制器与视图的绑定
- 简单的事件处理
- CSS基础样式应用
但对于复杂动画、自定义组件和高级布局等仍需进一步学习。计划继续加强这方面的学习。
踩坑心得:从错误中学习
1. 过度设计陷阱
在"航空货运管理系统"初版中,我过早引入设计模式,创建了大量不必要的接口和抽象层,导致系统复杂度陡增。后来明白,简单设计往往更可取,只有当简单设计无法满足需求或有明确扩展需求时,才考虑引入模式。
教训:先从简单实现开始,随着需求明确再逐步重构,避免"为设计而设计"。
2. 不懂得提取公共方法
早期作业中,我经常复制粘贴相似代码,仅做微小修改。这种做法虽然在短期内节省时间,但导致后期维护困难,需要修改时要在多处重复同样的改动,极易遗漏。
改进:学会提取公共方法、使用继承和组合消除重复,现在我会先思考是否有重构空间,再开始编码。
3. 测试不足
多次因为未充分测试边界条件和未考虑“Wrong Format”的情况,在PTA提交后才发现问题。
改进:现在我会先设计测试用例,包括正常情况、边界情况和异常情况,确保主要场景都被覆盖。
4. 性能忽视
在"统计Java关键词"题目中,最初使用简单的字符串遍历和ArrayList查找,处理大文件时速度极慢。后来学习才了解HashSet存储关键词可以使得性能提升数倍。
收获:开始关注数据结构和算法复杂度,学会根据场景选择合适集合类。
改进建议与课程总结
对课程的建议
-
阶段性项目复盘:建议在每个主要知识点(如继承、多态、集合等)结束后,安排一个小型复盘会议,让学生分享实现思路和遇到的问题,促进经验交流。
-
PTA题目解析:对于通过率较低的难题,在题集结束后可以提供教师或助教的解题思路视频讲解,帮助理解题目考察重点和设计思路。
-
实验指导细化:JavaFX等实践性强的部分,可以提供更详细的步骤指导和常见问题解答,降低入门门槛。
个人学习总结
回顾整个学期的学习历程,我从一个只能写面向过程代码的新手,成长为能够运用面向对象思想设计中小型程序的入门者,这个转变令人欣喜。最大的收获不是语法细节,而是一种思维方式——如何通过抽象、封装、分层来管理复杂性,构建可维护、可扩展的软件系统。
课程中的几个关键转折点:
- 第一次成功运用继承消除重复代码时的成就感
- 理解多态机制后,设计出灵活扩展的系统架构
- 通过调试复杂BUG,培养出耐心和系统性思维
- 在团队实验中学会沟通协作和代码规范的重要性
对于仍感不足的部分,我的后续学习计划:
- 继承与多态:通过LeetCode面向对象题目加强练习,阅读《Head First Java》相关章节
- JavaFX:开发一个个人兴趣项目(如简易钢琴模拟器),实践各种UI组件和事件处理
- 设计模式:逐步学习常用的设计模式,理解它们解决的问题场景
- 工程实践:学习单元测试、持续集成等现代软件开发实践
这门课程不仅教会了我Java编程,更重要的是培养了我分析问题、设计解决方案的系统化思维能力。虽然学习过程充满挑战,但每一次突破都带来成长的喜悦。面向对象思想将成为我未来学习和职业发展的坚实基础,这段学习经历值得永远铭记。
浙公网安备 33010602011771号