当你要定义“能做什么”、强调行为契约、需要多能力组合或解耦实现与调用时,就该用接口;如多身份(payservice & retryable)、跨类型统一行为(comparable)、面向接口编程(userrepository)等场景。

面试时被问“什么时候该用接口”,别一上来就背语法区别。面试官想听的是你对设计意图的理解和真实场景的判断力。
核心一句话回答
当你要定义“能做什么”、强调行为契约、需要多能力组合,或者要解耦实现与调用时,就该用接口。
看是否需要“多个身份”或“跨类型能力”
一个类往往不止属于一个类别,但 Java 只允许单继承。比如一个类既是 PayService(支付服务),又需要支持 Retryable(可重试)、Loggable(可打日志)、Serializable(可序列化)。这些能力彼此无关,也不构成“父子关系”。
- 用接口:可以同时
implements PayService, Retryable, Loggable - 用抽象类:只能选一个父类,其他能力无法统一建模
看是否要约束不相关类的统一行为
比如 Comparable、Cloneable、Runnable——字符串、日期、自定义订单对象,它们毫无继承关系,但都需要“能比较”“能克隆”“能运行”。
- 接口天然适合这种横向能力约定
- 抽象类要求“是同一类事物”,比如所有
Animal子类都共享生命周期逻辑,这才适合抽象类
看是否要面向接口编程、便于替换和测试
框架设计和业务分层中,接口是解耦的关键。比如 DAO 层定义 UserRepository 接口,实现可以是 MyBatis、JPA,甚至内存 Map 模拟。调用方只依赖接口,不关心具体实现。
- 接口让依赖倒置成为可能,方便单元测试(Mock 接口)
- 抽象类带状态和构造逻辑,耦合更强,不适合做这种“契约式”依赖
注意一个常见误区
Java 8 后接口支持 default 方法,有人觉得“接口也能复用代码,那跟抽象类差不多了”。其实不是:
-
default方法是为向后兼容而生,本质仍是“行为扩展”,不是为了封装状态或初始化逻辑 - 接口不能有构造器、不能存实例变量、不能
protected成员——它依然无法替代抽象类在“共性实现+状态管理”上的作用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











