java不支持类多继承,但接口可使用extends关键字多继承多个父接口,仅传递方法签名和default/static成员,实现类必须覆盖所有抽象方法;同名default方法冲突需在实现类中显式重写解决。

接口多继承只发生在接口之间,用 extends 关键字
Java 不允许类多继承(class A extends B, C 直接编译报错),但接口可以合法地同时继承多个父接口。这不是“模拟”,而是语言原生支持的语法:一个接口能通过 extends A, B, C 组合多个契约定义。
例如:Flyable 和 Swimmable 各自声明一组行为,Duck 接口继承二者后,就天然承载了三个契约:fly()、swim()、quack()。后续任何实现 Duck 的类,都必须覆盖全部抽象方法。
- 接口多继承不传递字段、构造器或私有方法,只传递方法签名和
default/static方法 -
public static final常量会被继承,但无法新增实例状态 - 过度嵌套(如
I extends J, K; J extends L, M)会让实现类承担大量隐式义务,调试时容易漏实现
类实现多个接口是日常主力方案,用 implements 分隔
你真正写业务逻辑时,几乎不会让类去继承接口,而是让类 implements 多个接口。这等于向系统承诺:“我提供这些行为”,而不是“我复制了这些代码”。
比如:Robot implements Flyable, Swimmable, SelfDiagnosable —— 它必须自己写出 fly()、swim()、diagnose() 的具体逻辑,不能靠父类转发。
- 所有抽象方法都必须由实现类显式覆盖,否则编译失败(除非该类声明为
abstract) - 多个接口里有同名抽象方法(如都定义了
start()),只要签名一致,实现一次即可,不冲突 - 如果签名看似相同但参数类型不同(如
start(String)vsstart(int)),那就是重载,需分别实现
同名 default 方法冲突必须在实现类中显式解决
当类实现的多个接口都提供了同签名的 default 方法(如 A.default run() 和 B.default run()),Java 编译器会拒绝通过,报错:class inherits unrelated defaults for method run。
你不能回避,必须在实现类里用 @Override 显式写出 run() 方法体,并决定调用路径:
- 直接调用某一方:
A.super.run()或B.super.run() - 合并逻辑,写新实现(推荐):比如把两个默认行为串起来,或加日志、校验等
- 不要机械转发——如果两个
default方法都涉及状态变更或 IO,说明接口职责已混淆,该重构了
组合行为时最容易忽略初始化顺序和空引用问题
接口本身不管理生命周期,但当你用组合模式替代继承(比如在类里持有一组接口类型的成员变量),实际编码中常踩两个坑:
- 构造函数里未完成依赖注入,导致某个
Swimmable swimmer字段为null,运行时报NullPointerException - 多个组件初始化顺序没对齐,比如
Logger组件还没 ready,NetworkClient就开始调用它打日志 -
default方法若内部调用了本接口其他default方法,而后者又被子接口重写,行为可能偏离预期——这种链式调用很难静态分析
复杂点不在语法,而在契约边界是否清晰:一个接口该管什么、不该管什么,决定了后续组合时要不要补胶水代码、会不会被默认方法悄悄绑架。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











