当多个接口定义同名同签名default方法时,Java强制要求实现类必须显式重写并用InterfaceName.super.methodName()调用指定实现,否则编译失败;若父类已提供同签名方法则无需重写。

当一个类实现多个接口,而这些接口都定义了同名、同参数、同返回类型的 default 方法时,Java 编译器会直接报错:“class inherits unrelated defaults for method() from types A and B”。这不是警告,而是编译失败——你必须重写该方法。
必须显式重写冲突方法
不能只声明方法签名,也不能留空方法体。哪怕两个默认方法逻辑完全一致,也得在实现类中写出完整方法体,并用 @Override 标注:
- 错误写法:
public void save() {}(空实现,未解决语义歧义) - 错误写法:
public void save() { super.save(); }(super在接口多重实现中无意义,编译不通过) - 正确写法:
@Override public void save() { Repository.super.save(); }
用 InterfaceName.super.methodName() 调用指定实现
这是 Java 唯一允许的跨接口调用默认方法的方式,只能在你已重写的同名方法体内使用:
- 接口名不可省略,例如
A.super.log(),不能写成super.log() - 仅适用于
public default方法,static或private default不可用 - 可在同一方法中组合调用,比如先执行
A.super.log(),再做参数校验或日志增强 - 不能在静态方法、lambda 表达式或构造器中使用
优先级规则决定是否需要重写
不是所有“同名”都会触发冲突。是否必须重写,取决于继承链中的方法来源:
立即学习“Java免费学习笔记(深入)”;
- 如果父类(含抽象类)已有同签名的
public或protected方法,则所有接口默认方法被忽略,无需重写 - 如果某个接口只声明抽象方法(无
default),另一个有default,则必须实现抽象方法,default版本自动失效 - 若接口之间存在继承关系(如
B extends A),且都未覆写A的default方法,实现类仍可能因菱形结构触发冲突
从设计上减少后续麻烦
与其每次补救,不如前期规避:
- 接口方法命名带领域前缀,例如
httpLog()、cacheEvict(),避免泛泛叫log()或clear() - 通用能力(日志、重试、序列化)优先抽成工具类或抽象基类,别塞进多个业务接口
- 谨慎添加
default方法——它适合向后兼容的轻量增强,不适合核心可变行为 - 发现多个模块反复出现同类冲突,说明接口职责划分不清,值得推动重构


















