




Java 8 默认方法解决接口演进的向后兼容问题,允许在不破坏现有实现类的前提下添加新行为;它属于实例方法,可被实现类对象调用,用于需访问实例数据的场景,而 static 方法属工具性逻辑,通过接口名调用。
Java 8 引入接口默认方法(default 方法),核心是解决「向后兼容的接口演进」问题——即在不破坏已有实现类的前提下,给接口添加新行为。
因为所有已存在的实现类会立刻编译失败:缺少对新 abstract 方法的实现。尤其在大型生态(如 Spring、Apache Commons)中,强制所有下游实现者同步修改根本不可行。
默认方法绕过该限制:
public interface List{ default void replaceAll(UnaryOperator operator) { // JDK 8 新增,默认实现,老实现类无需改动 Objects.requireNonNull(operator); final ListIterator li = this.listIterator(); while (li.hasNext()) { li.set(operator.apply(li.next())); } } }
ArrayList、LinkedList 等无需重写该方法即可直接调用
replaceAll
default 方法属于实例行为,可通过实现类对象调用;static 方法属于接口自身,只能通过接口名调用(如 Collection.size() 不合法,但 Collection.unmodifiableList() 合法)。
default:需要访问实现类提供的实例数据(例如遍历 this 集合)static:工具性逻辑,不依赖具体实现(如工厂方法、常量构造)private(Java 9+ 才支持 private default 方法)当一个类同时实现多个接口,且它们都有同签名的 default 方法,编译器会报错:class X inherits unrelated defaults for method Y from types A and B。
A.super.method() 或 B.super.method() 显式调用某一方default 方法被其子接口覆写为 abstract,则该子接口的实现类必须提供实现(优先级高于父接口默认实现)真正容易被忽略的是:默认方法不是“语法糖”,它改变了 Java 接口的语义边界——接口开始承担部分行为契约,而不仅是类型声明。这意味着设计接口时,要更谨慎地权衡「哪些能力真的该由接口兜底」,否则会模糊抽象与实现的职责边界。