应优先用继承表达is-a关系(如“学生是一种人”),用成员变量表达has-a关系(如“汽车有一个发动机”);判断标准是:“B是A的一种吗?”选继承,“A是否需存B实例来做事?”选组合。

关键看类之间是“属于什么类型”,还是“拥有什么部件”——前者用继承,后者用成员变量。
is-a 关系:用 extends 或 implements 表达“是一种”
当一个类在逻辑上是另一个类的特例时,就属于 is-a。比如“苹果是一种水果”“安卓手机是一种手机”“学生是一种人”。这种关系强调类型归属和共性复用。
- Java 中通过 extends(类继承) 或 implements(接口实现) 实现
- 子类能直接使用父类的非私有成员,也能被多态调用(如
Animal a = new Dog();) - 错误示例:把“操作系统”做成 WindowsPC 的子类——WindowsPC 不是操作系统的一种,这是典型的 is-a 误用
has-a 关系:用成员变量表达“有一个”
当一个类内部需要使用另一个类的对象来完成自身功能时,就是 has-a。比如“汽车有一个发动机”“人有一个身份证”“订单有一个收货地址”。这种关系体现结构组成,不改变类型本质。
- Java 中通过声明 成员变量(字段) 实现,类型可以是任意类或接口
- 被包含的对象生命周期通常由宿主类管理(组合),也可独立存在(聚合)
- 正确示例:PC 类中定义
private String os;或private OperatingSystem os;,而不是让 WindowsPC 继承 OperatingSystem
怎么快速判断该用哪个?问自己两个问题
写代码前停一秒,自问:
立即学习“Java免费学习笔记(深入)”;
- “B 是 A 的一种吗?” → 是 → is-a → 考虑继承或实现
- “A 里面要不要存一个 B 的实例来做事?” → 是 → has-a → 定义字段
比如设计 Employee 类:
– “员工是人” → is-a → 可继承 Person
– “员工有一个工牌、有一份合同、属于一个部门” → has-a → 声明 Badge badge;、Contract contract;、Department dept;
别混淆 is-a 和 has-a 的常见陷阱
初学者容易把属性差异当成类型差异:
- 错:为“张三”“李四”分别建
ZhangSan和LiSi类,都继承Person→ 名字是属性,不是类型 - 错:让
Car继承Engine→ 汽车不是发动机的一种,而是“有一个发动机” - 对:把
Engine作为Car的私有字段,必要时还可替换(比如电动车换电机)→ 更灵活,更符合现实



















