接口与抽象类分工协作:接口定契约、用default方法补轻量无状态逻辑;抽象类管骨架、持状态、强约束初始化;组合方式为extends抽象类+implements多接口。

接口默认方法和抽象类不是替代关系,而是分工协作:接口定契约、划边界,抽象类管骨架、藏状态。协同的关键在于让调用方只关心“能做什么”,集成方只操心“怎么复用”。
接口用 default 方法补轻量契约,不碰核心流程
默认方法适合封装无状态、正交、极简的通用逻辑,比如空值检查、基础转换、日志打点等。它本质是“契约的友好补丁”,不是业务主干。
- 例如 NotificationService 接口可加 default void logSent(String id) { logger.info("sent: {}", id); },所有实现自动获得基础日志能力
- 避免在 default 方法里访问 this 字段、调用构造参数、做资源初始化——这些必须交给抽象类
- 若两个接口都定义了同名 default 方法(如 Retryable.hook() 和 Tracable.hook()),实现类必须显式重写并明确调用策略,否则编译失败
抽象类承载有状态的模板流程,强制约束初始化
抽象类是真正能“hold 住上下文”的地方:它有构造器、protected 字段、初始化块、final 模板方法,能把 HTTP 客户端、配置、签名密钥等关键依赖在创建时就绑定好。
- 比如 AbstractPaymentClient 可要求 public AbstractPaymentClient(Config config, Signer signer),确保子类无法绕过凭证校验
- 用 final Response execute(Request r) 封装“签名→序列化→调用→异常映射”全流程,只留 abstract HttpRequest buildRequest() 由子类定制
- 工具方法如 protected String encryptCardNo(String no) 可被子类安全调用,但不对外暴露,也不污染接口契约
组合方式:extends 抽象类 + implements 多接口,能力正交叠加
一个 SDK 实现类应先继承统一骨架,再按需实现能力接口。每个接口代表一个可插拔维度,彼此不耦合。
- 典型写法:class WechatPayClient extends AbstractHttpClient implements AsyncCapable, Idempotent, AuditLoggable
- AsyncCapable 提供 default CompletableFuture
asyncCall(...),Idempotent 提供 default String generateIdempotencyKey(...),二者互不影响 - 若抽象类中已内置带熔断的重试引擎,而 Retryable 接口只提供轻量 default retry(),子类可选择直接 super.retry() 或覆盖为更严格的策略
警惕职责错位:别让 default 方法变“迷你抽象类”
当 default 方法开始需要读取成员变量、调用其他 default 方法形成链路、或依赖构造参数时,说明它已经越界——该抽成抽象类里的 protected 方法了。
- 反例:OrderProcessor 接口中写 default void validateAndLock() { this.lockOrder(); this.checkStock(); } —— this 不合法,且锁和库存校验明显属于有状态流程
- 正解:把 validateAndLock() 提到 AbstractOrderProcessor 中,作为 final 模板方法,由子类实现 doValidate() 和 doLock()
- 接口仍保留 public boolean isValid() 和 public void lock() 两个抽象方法,保持契约清晰、可测、可 Mock
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











