Java面向对象实验1到6全解析:类与对象、封装、继承、多态、集合与异常处理

发布时间:2026/10/23 16:19:18
Java面向对象实验1到6全解析:类与对象、封装、继承、多态、集合与异常处理 简介这份资源是东北大学Java面向对象实验1至6的完整代码合集面向正在修读该课程的学生以及希望系统练习OOP核心语法的自学者可解决实验无从下手、代码结构混乱、知识点难以串联等问题。压缩包共124个文件约51KB以java源码与class字节码为主辅以html说明页、xml配置、dat数据文件及少量gif与jar覆盖类与对象、封装、继承、多态、构造器、接口、异常处理、集合框架、文件流、复杂数据结构与设计模式等实验主题从内容预览可见还包含图形界面与目录加载相关模块。目前已有2002人学习下载说明该套代码在课程学习者中认可度较高。读者可对照六个实验的完整实现理解私有变量与公共方法的封装思路、父子类继承关系、接口实现与多态调用并参考异常捕获与集合存储的写法快速搭建可运行工程、排查编译与运行错误为后续Java项目开发打下扎实基础。1. 从零到一Java 面向对象实验的知识地图长什么样很多人复习 Java 面向对象实验时第一反应是翻代码、背语法结果到了考场或项目里还是不知道类该怎么拆、接口该不该抽。这套实验代码 1 到 6 的价值不在于“能跑”而在于它把面向对象的核心概念按认知顺序串成了一条线从类与对象的基本建模到封装、继承、多态三大特性再到接口与抽象类的取舍最后落到集合与异常处理的综合运用。梳理下来会发现六个实验其实对应六个递进的能力台阶每个台阶都在解决上一阶段遗留的设计问题。如果你正在系统学 Java 或者准备实验考核这份代码就是一张可以逐题对照的知识地图帮你把零散语法点挂到面向对象的骨架上。2. 实验 1 到 2类与对象、封装——从“能跑”到“像样”2.1 类与对象第一个实验到底在练什么实验 1 通常要求定义一个简单的类比如学生类、矩形类或银行账户类然后创建对象、调用方法、访问属性。很多人觉得这太简单随便写个main方法就交了。但梳理下来会发现这个实验真正训练的是“识别职责”——哪些数据应该放在类里哪些行为应该由对象自己完成。以银行账户为例一个合格的实验 1 代码应该长这样public class BankAccount { private String ownerName; private double balance; public BankAccount(String ownerName, double initialBalance) { this.ownerName ownerName; this.balance initialBalance; } public void deposit(double amount) { if (amount 0) { throw new IllegalArgumentException(存款金额必须为正数); } balance amount; } public void withdraw(double amount) { if (amount balance) { throw new IllegalStateException(余额不足); } balance - amount; } public double getBalance() { return balance; } }这段代码的关键不在语法而在三个设计决策属性用private修饰、构造函数负责初始化、存取款方法自带校验逻辑。实验 1 最容易翻车的地方就是把所有属性写成public然后在main方法里直接改值。这样写虽然能跑但完全丢掉了面向对象的第一层意义——对象应该自己管理自己的状态。参数说明ownerName和balance是账户的核心状态deposit和withdraw是行为getBalance是只读访问接口。构造函数里的initialBalance允许调用方在创建对象时指定初始金额避免创建出“无主账户”。2.2 封装为什么第二个实验总在改第一个实验的代码实验 2 通常要求对实验 1 的类进行改造加入private属性、getter/setter方法并可能引入包的概念。这个实验的典型场景是把学生类的年龄属性改成私有然后通过setAge方法限制年龄范围。public class Student { private String name; private int age; public void setAge(int age) { if (age 0 || age 150) { throw new IllegalArgumentException(年龄不合法); } this.age age; } public int getAge() { return age; } }这里最容易忽略的是setter方法不是简单赋值而是数据校验的入口。很多同学写setAge时直接this.age age;那封装就白做了。封装的本质是“控制访问”不是“加个 get/set 就完事”。重点难点在于什么时候该提供setter什么时候只提供getter。比如账户余额通常只提供getBalance不提供setBalance因为余额只能通过存取款行为改变。这个判断标准在实验 2 里就要建立起来否则后面实验 3 的继承会写得很乱。提示实验 1 和实验 2 的代码要对照着看重点观察“哪些属性从 public 变成了 private”“哪些方法从直接赋值变成了带校验的 setter”。这个变化过程就是封装思想的落地。3. 实验 3 到 4继承、多态与抽象类——代码复用的分水岭3.1 继承extends 背后的“是一个”关系实验 3 通常要求设计一个继承体系比如Person作为父类Student和Teacher作为子类。这个实验的核心不是记住extends关键字而是理解“子类是一种父类”的语义。public class Person { protected String name; protected int id; public Person(String name, int id) { this.name name; this.id id; } public String getInfo() { return 姓名 name 编号 id; } } public class Student extends Person { private String major; public Student(String name, int id, String major) { super(name, id); this.major major; } Override public String getInfo() { return super.getInfo() 专业 major; } }这段代码里super(name, id)调用父类构造函数Override注解表示重写父类方法。实验 3 最容易踩的坑是子类构造函数没有显式调用super(...)导致父类属性没有被正确初始化。另一个坑是父类属性用了private子类无法直接访问只能用protected或通过getter访问。重点难点在于继承的层次不宜过深一般不超过三层。实验 3 里如果出现A extends B extends C extends D就要反思是不是设计过度了。梳理下来会发现继承的真正价值是“把公共代码上提到父类”而不是“为了继承而继承”。3.2 多态父类引用指向子类对象的实战意义实验 4 通常要求用多态实现一个简单的“图形面积计算”或“员工薪资计算”场景。核心写法是父类引用数组存放不同子类对象循环调用同一个方法运行时根据实际类型执行不同逻辑。abstract class Shape { abstract double area(); } class Circle extends Shape { private double radius; Circle(double radius) { this.radius radius; } Override double area() { return Math.PI * radius * radius; } } class Rectangle extends Shape { private double width, height; Rectangle(double width, double height) { this.width width; this.height height; } Override double area() { return width * height; } } public class Main { public static void main(String[] args) { Shape[] shapes { new Circle(3), new Rectangle(4, 5) }; for (Shape s : shapes) { System.out.println(面积 s.area()); } } }这段代码的关键在于Shape[] shapes这个数组——它声明的是父类类型但实际存放的是子类对象。循环里的s.area()在编译时看的是Shape类有没有area方法运行时才决定调用Circle还是Rectangle的实现。这就是多态的核心编译看左边运行看右边。实验 4 最容易出错的地方是父类方法没有用abstract修饰或者子类重写时方法签名不一致比如参数类型或返回值不同导致多态失效。另一个常见问题是在main方法里用instanceof加强制类型转换来分别处理那就退化成面向过程了完全没用到多态。注意抽象类不能实例化但可以声明引用变量。Shape s new Shape();会直接编译报错这个错误在实验 4 里出现频率很高。3.3 抽象类与接口实验 4 后半段的取舍逻辑实验 4 往往还会引入接口比如Comparable或自定义的Printable接口。这时候就要区分抽象类和接口的使用场景抽象类用于“同类事物的公共模板”接口用于“跨类事物的能力约定”。interface Printable { void print(); } class Report implements Printable { private String content; Report(String content) { this.content content; } Override public void print() { System.out.println(打印报告 content); } }如果实验 4 要求同时使用抽象类和接口典型的做法是抽象类定义“是什么”接口定义“能做什么”。比如abstract class Employee定义员工的基本属性interface Payable定义“可计算薪资”的能力。这样设计的好处是一个类只能继承一个抽象类但可以实现多个接口灵活性更高。重点难点接口中的方法默认是public abstract的不能有方法体Java 8 之后可以有default方法但实验代码通常不涉及。实现接口时方法必须用public修饰否则编译报错。这个细节在实验 4 里经常被忽略。4. 实验 5 到 6集合、异常与综合实战——从单点到系统4.1 集合框架ArrayList 与 HashMap 的实验用法实验 5 通常要求用集合存储对象比如用ArrayList管理学生列表用HashMap存储学号与学生的映射关系。这个实验的核心是根据场景选择正确的集合类型。集合类型底层结构适用场景实验中的典型用法ArrayList动态数组频繁按索引访问、尾部插入存储学生列表遍历输出LinkedList双向链表频繁头部插入删除实验代码中较少出现HashMap哈希表键值对快速查找学号到学生对象的映射HashSet哈希表去重存储不重复的标签或类别import java.util.*; public class StudentManager { private MapString, Student studentMap new HashMap(); public void addStudent(Student s) { studentMap.put(s.getId(), s); } public Student findById(String id) { return studentMap.get(id); } public ListStudent getAllStudents() { return new ArrayList(studentMap.values()); } }这段代码里HashMap负责按学号快速查找ArrayList负责返回有序列表。实验 5 最容易犯的错是用ArrayList存学生后每次查找都遍历整个列表时间复杂度 O(n)。如果实验要求“按学号查找”就应该用HashMap查找时间接近 O(1)。重点难点HashMap的key必须正确重写hashCode和equals方法否则查找会失败。实验代码里如果自定义对象作为key一定要检查这两个方法有没有重写。4.2 异常处理try-catch-finally 的实验写法实验 6 通常要求加入异常处理比如自定义异常类、在方法中抛出异常、在调用处捕获并处理。这个实验的核心是区分受检异常和非受检异常并合理使用try-catch-finally。class InsufficientBalanceException extends Exception { public InsufficientBalanceException(String message) { super(message); } } public class Account { private double balance; public void withdraw(double amount) throws InsufficientBalanceException { if (amount balance) { throw new InsufficientBalanceException(余额不足当前余额 balance); } balance - amount; } }调用方代码public class Main { public static void main(String[] args) { Account acc new Account(); try { acc.withdraw(1000); } catch (InsufficientBalanceException e) { System.out.println(取款失败 e.getMessage()); } finally { System.out.println(交易结束); } } }这里的关键点有三个自定义异常继承Exception表示受检异常调用方必须处理throws声明在方法签名上throw写在方法体内finally块无论是否发生异常都会执行适合放资源释放代码。实验 6 最容易漏掉的是finally块里如果也有return语句会覆盖try块里的返回值。这个坑在实验代码里不一定出现但复习时要心里有数。4.3 综合实战六个实验串起来看设计模式雏形把实验 1 到 6 连起来看会发现一条清晰的设计演进线实验 1 定义类实验 2 封装属性实验 3 抽取父类实验 4 用多态统一接口实验 5 用集合管理对象实验 6 用异常处理边界情况。这套流程本身就是一个小型系统的开发缩影。梳理下来会发现实验 5 和实验 6 的代码里已经隐约出现了“分层”的思想StudentManager负责管理集合Student负责自身数据Main负责调用。如果实验 6 要求写一个完整的控制台程序典型的代码结构应该是public class Main { public static void main(String[] args) { StudentManager manager new StudentManager(); Scanner scanner new Scanner(System.in); while (true) { System.out.println(1. 添加学生 2. 查找学生 3. 退出); int choice scanner.nextInt(); scanner.nextLine(); try { switch (choice) { case 1: System.out.print(输入学号); String id scanner.nextLine(); System.out.print(输入姓名); String name scanner.nextLine(); manager.addStudent(new Student(id, name)); break; case 2: System.out.print(输入学号); Student s manager.findById(scanner.nextLine()); if (s ! null) { System.out.println(s.getInfo()); } else { System.out.println(未找到该学生); } break; case 3: return; default: System.out.println(无效选项); } } catch (Exception e) { System.out.println(操作异常 e.getMessage()); } } } }这段代码把集合、异常、面向对象都串起来了。重点在于try-catch包住了整个switch任何一步出错都不会导致程序崩溃。实验 6 的评分点往往就在这里——程序能不能在用户输入非法数据时继续运行。5. 易漏点与易错点六个实验里最容易翻车的五个地方5.1 构造函数没有初始化所有属性易漏点子类构造函数忘记调用super(...)或者父类没有提供带参构造函数。为什么漏实验 3 里父类如果只写了带参构造函数子类不显式调用super就会编译报错。很多人直接加个无参构造函数“糊弄”过去结果父类属性全是默认值。怎么补父类只提供带参构造函数时子类必须用super(参数)显式调用。如果父类有无参构造函数子类可以省略super()但属性初始化要自己保证。5.2 重写 equals 却没重写 hashCode易漏点自定义对象作为HashMap的 key 时只重写了equals没重写hashCode。为什么漏实验 5 里用学号作为 key 时如果 key 是String类型Java 已经帮你重写好了。但一旦用自定义对象作为 key两个equals相等的对象hashCode不同HashMap就找不到。怎么补用 IDE 自动生成equals和hashCode或者手动确保两个方法基于同一组属性计算。5.3 多态调用时方法签名不一致易漏点子类“重写”父类方法时参数类型或返回值写错了变成了重载而不是重写。为什么漏实验 4 里父类方法double area()子类写成double area(int x)编译能过但多态调用时永远执行父类方法。怎么补重写时加Override注解编译器会帮你检查签名是否一致。5.4 finally 块里写 return 覆盖返回值易漏点try块里return a;finally块里return b;最终返回b。为什么漏实验 6 里如果finally块用来关闭资源顺手写了return就会吞掉try块的返回值。怎么补finally块只做资源释放不要写return、break、continue。5.5 集合遍历时删除元素导致异常易漏点用for-each遍历ArrayList时调用remove抛出ConcurrentModificationException。为什么漏实验 5 里如果要“删除所有不及格学生”直接在循环里list.remove(s)就会翻车。怎么补用Iterator的remove方法或者用removeIfIteratorStudent it list.iterator(); while (it.hasNext()) { Student s it.next(); if (s.getScore() 60) { it.remove(); } }6. 复习清单六个实验的查漏补缺路线图复习这套实验代码最有效的方式不是从头到尾重读而是按“能力点”逐项自查。下面这份清单按实验顺序排列每一项都对应一个可验证的代码能力。你可以对着自己的代码逐条打勾哪一项卡住了就回到对应实验的代码里找答案。能力点对应实验自查标准常见问题类定义与对象创建实验 1能写出带私有属性、构造函数、行为方法的类属性全 publicmain 里直接改值封装与数据校验实验 2setter 方法里有范围校验不是简单赋值setter 只写this.x x继承与 super 调用实验 3子类构造函数显式调用super(...)忘记调用父类属性未初始化多态与抽象类实验 4父类引用数组存放子类对象循环调用用 instanceof 分别处理接口实现实验 4实现类方法用 public 修饰方法没加 public编译报错集合选型实验 5按查找需求选 HashMap按顺序选 ArrayList一律用 ArrayList查找靠遍历异常处理实验 6自定义异常继承 Exception调用方 try-catch异常被吞掉没有输出信息综合程序结构实验 6Main 类只负责交互业务逻辑在 Manager 类所有代码堆在 main 方法里复习时建议按这个顺序走先看实验 1 和 2 的代码确认封装有没有做到位再看实验 3 和 4确认继承体系是否合理、多态有没有真正用起来最后看实验 5 和 6确认集合选型和异常处理有没有踩坑。每看完一个实验把对应的代码默写一遍重点默写构造函数、重写方法、集合操作和 try-catch 结构。梳理下来会发现这套实验代码的真正价值不在于“六个题目”而在于它把面向对象的三大特性、集合框架、异常处理这些知识点按认知顺序排好了。你不需要额外找练习题把这六个实验的代码吃透Java 面向对象的核心考点就全覆盖了。从那以后我每次复习这套代码都会先画一张类关系图把每个实验的类、接口、继承关系标出来然后再对照代码检查多态和异常处理有没有遗漏。这个习惯帮我省了很多来回翻代码的时间。希望这份梳理也能帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询