一、💡 一句话理解
核心结论
接口定义“必须具备什么能力”,抽象类定义“同一类事物共有的状态和基础实现”。
记忆:接口看能力,抽象类看血缘和复用。
二、🧭 理论:它们是什么
2.1 接口
接口是一种引用类型,主要用来约定行为。类通过 implements 实现接口,并完成接口要求的方法。
interface Payable {
void pay(int amount);
}调用者只依赖 Payable,不需要关心具体使用支付宝、微信还是银行卡付款。
2.2 抽象类
抽象类用 abstract 修饰,不能直接创建对象,但可以被继承。它既能定义抽象方法,也能保存成员变量和已经实现的方法。
abstract class Payment {
protected String orderNo;
public Payment(String orderNo) {
this.orderNo = orderNo;
}
public void printOrder() {
System.out.println("订单号:" + orderNo);
}
public abstract void pay(int amount);
}三、⚙️ 理论:核心区别
3.1 对比表
| 对比项 | 接口 | 抽象类 |
|---|---|---|
| 主要目的 | 约定一种能力 | 抽取同类对象的公共部分 |
| 关键字 | interface、implements | abstract class、extends |
| 创建对象 | 不能直接实例化 | 不能直接实例化 |
| 方法 | 可包含抽象、default、static 等方法 | 可同时包含抽象方法和普通方法 |
| 成员变量 | 字段默认是 public static final 常量 | 可以保存普通实例状态 |
| 构造方法 | 没有构造方法 | 可以有构造方法,供子类初始化 |
| 继承数量 | 一个类可以实现多个接口 | 一个类只能直接继承一个类 |
3.2 怎么选择
- 多种没有共同父类的对象都要具备同一种能力:使用接口。
- 多个关系紧密的子类需要共享状态和代码:使用抽象类。
- 两者可以一起使用:接口负责对外约定,抽象类负责复用公共实现。
常见误区
接口并不等于“只能写抽象方法”。现代 Java 接口可以有
default和static方法;但接口仍不适合保存每个对象各自变化的实例状态。
四、🚀 实践:最小可运行示例
4.1 可以拿来干什么
支付系统需要统一调用不同支付方式,同时复用订单号打印逻辑:
Payable接口规定支付能力。BasePayment抽象类保存订单号并提供公共方法。WechatPayment继承公共代码,实现具体支付逻辑。
4.2 完整代码、启动和验证
文件:Demo.java
// 接口只约定支付能力,调用方可以面向接口编程。
interface Payable {
void pay(int amount);
}
// 抽象类实现接口,但可以暂时不实现 pay,由具体子类完成。
abstract class BasePayment implements Payable {
// 抽象类可以保存每个支付对象自己的订单号。
protected final String orderNo;
// 构造方法供子类初始化公共状态。
protected BasePayment(String orderNo) {
this.orderNo = orderNo;
}
// 普通方法直接复用,不要求每个子类重复编写。
public void printOrder() {
System.out.println("订单号:" + orderNo);
}
}
class WechatPayment extends BasePayment {
public WechatPayment(String orderNo) {
super(orderNo);
}
@Override
public void pay(int amount) {
System.out.println("微信支付:" + amount + " 元");
}
}
public class Demo {
public static void main(String[] args) {
WechatPayment payment = new WechatPayment("ORDER-1001");
payment.printOrder();
// 接口类型可以接收任意 Payable 实现,方便以后替换支付方式。
Payable payable = payment;
payable.pay(100);
}
}运行:
javac Demo.java
java Demo预期输出:
订单号:ORDER-1001
微信支付:100 元五、🎤 面试时怎么流利地说
5.1 回答路线
先说用途,再对比状态、方法、构造方法和继承数量,最后说明选择场景。
5.2 30 秒标准回答
接口主要用来定义能力和行为规范,一个类可以实现多个接口;抽象类主要用于关系紧密的子类之间复用状态和代码,一个类只能直接继承一个类。两者都不能直接实例化,也都可以包含抽象方法。如果只想约束行为,我会选择接口;如果还需要共享成员变量、构造逻辑和公共实现,我会选择抽象类。实际开发中也经常把两者结合使用。
5.3 高频追问与短答
- **抽象类一定有抽象方法吗?**不一定。只要类被
abstract修饰,它就是抽象类,也不能直接实例化。 - **接口可以有方法实现吗?**可以,例如
default和static方法。 - **抽象类可以实现接口吗?**可以。如果没有实现接口的全部抽象方法,该类继续声明为抽象类即可。
- **为什么接口支持多个,类继承只支持一个?**Java 允许一个类实现多个接口,从而获得多种类型能力;但一个类只能直接继承一个类,避免多份实例状态和实现带来的冲突。
六、📌 总结
- 接口强调“能做什么”,抽象类强调“是什么以及共用什么”。
- 接口适合解耦和扩展,抽象类适合共享状态和代码。
- 一个类可以实现多个接口,但只能直接继承一个类。
- 两者不是互斥关系,可以组合使用。
- 相关知识:4.重载和重写的区别。