钩子:两个真实场景
场景一:写"动物"体系,每个动物都必须会 makeSound()——但"动物"这个类根本不该被 new 出来(你见过"一只动物"吗?)。我们需要一个不能实例化、只用来立规矩的类:抽象类。
场景二:要让订单能排序、能比较大小。但 Comparable 的规矩和"继承谁"无关——订单、学生、字符串都要能比。规矩应该能"嫁接"到任何类上:接口。
抽象类:半成品图纸
abstract class Animal {
protected String name;
public Animal(String name) { this.name = name; }
public abstract void makeSound(); // 抽象方法:只有声明,没有方法体
public void sleep() { // 普通方法:可以有实现
System.out.println(name + "在睡觉");
}
}
三条规矩:
- abstract class 不能 new——半成品图纸造不了楼;
- 含抽象方法的类必须是抽象类;抽象类可以没有抽象方法(纯防 new 用);
- 子类必须重写全部抽象方法,否则子类也得声明为抽象类——规矩传给下一棒。
接口:纯粹的"能力合同"
interface Comparable2 {
int compareTo(Object other); // 天生 public abstract
}
interface Printable {
void print();
}
// 一个类只能 extends 一个父类,但能 implements 多个接口
class Order implements Comparable2, Printable {
private double amount;
@Override
public int compareTo(Object other) {
Order o = (Order) other;
return Double.compare(this.amount, o.amount);
}
@Override
public void print() {
System.out.println("订单金额:" + amount);
}
}
接口是能力合同:签了合同(implements),就必须把合同上所有方法实现出来。类和接口的关系不再是"是一种",而是"能干什么"——Order 能比较、能打印,这些能力和"订单是什么"互相独立。

终极对比表(面试直接背)
| 对比项 | 抽象类 | 接口 |
|---|---|---|
| 关系 | is-a(是什么) | can-do(能干什么) |
| 数量限制 | 单继承,一个爹 | 可实现多个 |
| 成员变量 | 任意 | 只能 public static final 常量 |
| 方法体 | 随便写 | Java 8 前不行;之后可有 default/static |
| 构造方法 | 有(给子类 super() 用) | 没有 |
| 典型场景 | 动物→猫狗这类骨架复用 | Comparable、Runnable 这类能力插头 |
选择口诀:是什么 → 抽象类;能干什么 → 接口。 还纠结时选接口——成本更低、组合更灵活,Java 官方新 API 也基本全用接口。
呼应回收
- 第 16 篇说"第 20 篇你会第三次见到 this"——上面 Order.compareTo 里的
this.amount就是第三次,参数 other 强转后也用了 this 区分; - 接口是多态的完美舞台:
Comparable2 c = new Order();完全是第 19 篇"编译看左边,运行看右边"的复用。
模块三毕业小结
封装(守住数据)→ 继承(复用代码)→ 多态(一个接口多种行为)→ 抽象类/接口(立规矩)。四大件到齐,从下一篇开始进模块四:常用 API 与集合——第一个主角就是天天见的 String。
本文示例代码均已本地实测通过,可直接运行。
对应文件:InterfaceDemo.java
橙码酱,分享更有用的技术知识,助你成为更优秀的开发者。