Java 课程思考题小记
简介
本文是 SWU 2023级《面向对象高级编程》的实验与作业文档中,部分提及的思考题QA汇总。
个人认为比较有意义,不仅用于考试复习,也显著加深了对 Java 语言特性的理解。
对象方法
Q:Java中,对象方法的代码存放在哪里?
A:方法代码存放在方法区中(JDK 8 之后在元空间 Metaspace 中)。
Q:对象方法执行时如何获取对象引用的?
A:对象方法执行时通过 this 获取对象引用,而 this 是 JVM 在调用实例方法时隐式传递的第一个参数。
封装
Q:如何通过访问修饰符 private 提高对象的封装性?
A:
- 隐藏内部实现细节:只能在类内部访问,防止外部直接依赖具体的实现
- 保护对象的状态完整性:如果允许直接访问类的成员变量,可能会导致不合理的或非法的值直接赋给变量,影响对象的状态。
- 支持更好的代码维护:如果将来需要修改类的实现或变量的具体逻辑,只需更新类的内部实现,外部代码无需更改。
Q:为什么要通过 public 类型的Getter和Setter方法来实现对象成员变量的访问?
A:提供受控的访问方式,确保数据的安全性和一致性。增强代码的灵活性和可维护性。实现面向对象编程的封装原则,为未来的扩展性提供支持。
输出比较
1 | public class Test { |
Q:这里的输出是什么?
A:尽管 g 的类型是 Geometry,而 c 的类型是 Circle,但它们都指向同一个对象,因此 ==
比较的结果是 true
。
注意:虽然父类变量能够存放子类型引用,但通过父类变量访问子类型对象时,受限于父类的定义。
1 | public class Test { |
多态与动态绑定
Background:在应用层编写一个几何形状面积求和的函数:
1 | public class Test { |
Q:当系统需要扩展,例如增加新的几何形状,这时应用层代码 areaSum()
需要修改吗?
A:areaSum 方法利用了多态,通过接收 Geometry 类型的数组来实现对所有几何形状的统一处理。不需要修改。
抽象类
Q:抽象类的父类必须是抽象类吗?
A:抽象类的父类不一定必须是抽象类。在 Java 中,抽象类可以继承自另一个抽象类,也可以继承自一个具体类,抽象类的本质是提供一种模板,允许包含抽象方法(没有实现的方法),要求子类必须实现这些方法。
举个例子,继承自一个具体类的抽象类中定义了新方法,它的子类继承了这个抽象类,实现了这个新方法。
Q:语法上的抽象与广义抽象概念的区别?
A:语法层面的抽象是 Java 提供的一种语言机制,通过 abstract
关键字实现,用于表示一种不完全实现的类或方法。
- 抽象类是不能被实例化的类,通常用于定义一组通用行为,而具体行为留给子类实现。
- 抽象方法是没有方法体的方法,必须由子类实现。
广义的抽象是面向对象编程中的一个核心思想,用于提取事物的共性或概念化,将复杂事物简化为可以理解的模型。
抽象不仅仅依赖于语法层面的 abstract,它也体现在接口、设计模式以及继承机制中,是一种设计理念,用于提升代码的复用性、可读性和扩展性。
多态与面向抽象编程
Background:统计几何形状面积的方法
1 | public class Test { |
Q:为什么数组 geoArray
中可以存放各类形状对象的引用?
A:
- geoArray 的类型是 Geometry[],而 Circle 和 Rectangle 都是 Geometry 的子类。
- Java 的多态特性允许使用父类类型的引用来存储子类对象的引用(即向上类型转换,Up-Casting)。
- 在运行时,geoArray 的每个元素仍然保留其真实的类型(如 Circle 或 Rectangle),这使得可以动态调用各自实现的方法。
Q:g.area()
的含义是什么?area()
是由谁来执行?
A:
- g.area() 调用的是当前对象 g 的 area() 方法。因为 g 是 Geometry 类型的引用,但在运行时会动态绑定到其实际类型(如 Circle 或 Rectangle)。
- area() 方法的具体实现是由 g 的实际对象类型决定的(即子类实现)。这是动态绑定(Dynamic Binding)的体现,Java 在运行时根据实际类型调用适配的方法。
Background:批量移动几何形状的方法
1 | public class Test { |
Q:抽象类中的抽象函数和接口中的抽象函数有什么区别?本质上是否相同?
A:区别包含以下几点:
- 定义方式:抽象类中的抽象函数使用 abstract 修饰方法,且所在类需要用 abstract 修饰,接口中的方法在 Java 8 之前默认是 public abstract 的。
- 默认修饰符:抽象类的方法可以是 protected 或 public,接口方法只能是 public,并且隐式带有 abstract。
- 继承限制:一个类只能继承一个抽象类,而一个类可以实现多个接口。
- 实现约束:抽象类的子类实现所有抽象方法,或者自身定义为抽象类,实现接口的类必须实现接口中所有的抽象方法。
那么本质上是否相同?
相同点:
- 两者的本质是用来定义规范,子类或实现类必须按照规范来提供具体实现。
- 抽象方法本质上就是一种约定,强制实现类实现约定的方法。
不同点:
- 抽象类更强调继承,是一种 “is-a” 的关系。
- 接口更强调行为的实现契约,是一种 “can-do” 的关系。