《Java 100 天进阶之路》第19篇:Java接口的作用和意义
第19篇:Java接口的作用和意义
📌 系列导航:《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第18篇:Java接口和抽象类的异同,default关键字 |
➡️ 下一篇:第20篇:Java初始化、构造器、对象创建的过程
一、核心知识点
- 接口的定义:一组方法签名的集合,表示一种契约或能力
- 接口的核心作用:
- 解耦:调用者只依赖接口,不依赖具体实现,便于替换和测试
- 多态:通过接口引用指向不同实现,实现运行时行为变化
- 扩展性:易于增加新的实现类,符合开闭原则
- 标准化:定义模块之间的通信协议(如 JDBC、Servlet 规范)
- 接口在框架设计中的应用(Spring 的
ApplicationContext、BeanPostProcessor) - 接口与设计模式:策略模式、工厂模式、代理模式、适配器模式等
二、通俗讲解(1分钟开心学)
1. 接口像一个“USB 插口”
想象你的电脑有一个 USB 接口(规范):它规定了插头形状、电压、数据传输协议。任何符合这个规范的设备(U盘、鼠标、键盘)都能插上去用。电脑不需要知道插入的是什么具体设备,只需要按照 USB 协议通信。
接口在 Java 中就是这样的“规范”或“合同”。它定义了“能做什么”,但不规定“怎么做”。
2. 接口的核心价值
- 解耦:上层业务不依赖底层实现细节。比如支付系统定义
Payment接口,支付宝、微信各自实现。上层调用Payment.pay(),换支付方式时只需换一个实现类,其他代码不用改。 - 多态:一个接口引用可以指向任意实现类对象。例如
List<String> list = new ArrayList<>();后面可以换成new LinkedList<>()。 - 扩展性:增加新功能只需新增实现类,原有代码不修改(符合开闭原则)。
- 可测试性:单元测试时可以用 Mock 对象代替真实实现(如数据库操作)。
3. 接口在框架中无处不在
Spring 框架大量使用接口:ApplicationContext、BeanFactory、Aware、InitializingBean 等。你只需要实现这些接口,框架就会在合适的时机调用你的代码。
三、实操代码案例 + 场景说明
场景:开发一个通知服务,支持多种通知方式(邮件、短信、微信),并方便后续增加新方式。
1. 定义接口(契约)
public interface Notifier {
void send(String to, String message);
}
2. 多种实现(解耦与多态)
public class EmailNotifier implements Notifier {
@Override
public void send(String to, String message) {
System.out.println("发送邮件到 " + to + ":" + message);
}
}
public class SmsNotifier implements Notifier {
@Override
public void send(String to, String message) {
System.out.println("发送短信到 " + to + ":" + message);
}
}
3. 业务代码依赖接口(不依赖具体类)
public class NotificationService {
private final Notifier notifier;
// 构造器注入接口(解耦)
public NotificationService(Notifier notifier) {
this.notifier = notifier;
}
public void notifyUser(String userId, String msg) {
// 实际中 userId 可能有对应的邮箱/手机号
notifier.send(userId, msg);
}
}
// 使用
public class Main {
public static void main(String[] args) {
// 很容易切换实现
Notifier notifier = new EmailNotifier();
// Notifier notifier = new SmsNotifier(); // 换短信只需改这一行
NotificationService service = new NotificationService(notifier);
service.notifyUser("user@example.com", "您的订单已发货");
}
}
4. 接口作为回调(策略模式)
public interface SortStrategy {
void sort(int[] arr);
}
public class QuickSort implements SortStrategy {
@Override public void sort(int[] arr) { /* 快排实现 */ }
}
public class BubbleSort implements SortStrategy {
@Override public void sort(int[] arr) { /* 冒泡实现 */ }
}
// 使用策略
public class DataProcessor {
public void process(int[] data, SortStrategy strategy) {
strategy.sort(data);
// 后续处理...
}
}
四、避坑要点
| 错误/误区 | 后果 | 正确做法 |
|---|---|---|
| 接口设计得过于臃肿(几十个方法) | 实现类负担过重,违反接口隔离原则 | 拆分成多个小接口 |
| 接口中定义常量(常量接口反模式) | 污染命名空间,实现类无意义地继承常量 | 常量放在枚举或工具类中 |
| 空接口(标记接口)滥用 | 没有实际语义,增加混乱 | 使用注解替代 |
| 方法返回类型用具体实现类而非接口 | 降低了灵活性和可替换性 | 返回接口类型(如 List 而非 ArrayList) |
五、面试高频考点
Q1:什么是面向接口编程?有什么好处?
面向接口编程是指依赖抽象(接口)而非具体实现。好处:解耦、易扩展、易测试、支持多态。
Q2:接口和抽象类如何选择?
优先使用接口,因为可多实现。需要共享状态、构造逻辑或非公共方法时,用抽象类。很多框架提供“接口 + 抽象基类”的模式。
Q3:接口中能否包含静态方法?从哪个版本开始支持?
可以。Java 8 允许接口定义
static方法,通过接口名调用,常用于提供工具方法,如Comparator接口有静态方法comparing()。
六、练习题
- 设计:定义一个
Cache接口,包含put(key, value)、get(key)、remove(key)方法,分别实现RedisCache和LocalCache(模拟)。 - 代码阅读:下面代码有什么问题?
public interface UserService { void addUser(User user); } public class UserServiceImpl implements UserService { //... } // 在控制器中 UserServiceImpl service = new UserServiceImpl(); // 直接依赖具体类 - 动手:用接口+策略模式实现一个计算器,支持加减乘除四种策略,并可以动态切换。
📊 你的学习进度
- 当前:第19篇 / 共44篇 · 第二阶段:核心语法与面向对象(第5~20篇)
- ✅ 已完成:第1~18篇
- 📖 正在学:第19篇
- ⏳ 待学习:第20~44篇
👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇
💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!
👉 下一篇预告
《Java初始化、构造器、对象创建的过程》
内容简介:成员初始化顺序(静态→实例→构造),对象创建的JVM流程,父子类初始化顺序口诀。
💡 学完这篇,你将彻底搞清楚“对象到底是怎么创建的”,面试必考。
📌 《Java 100 天进阶之路 | 从入门到上岗就业》 每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!
更多推荐




所有评论(0)