# 简介
接口可以有实现方法,而且不需要实现类实现其方法,只需要在方法名前加上 default
关键字。
为什么要有这个特性?首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8 之前的集合框架没有 foreach 方法,通常能想到的解决办法是在 JDK 里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。
在简单点说就是,假设我某一个接口需要定义一个新的行为,这个行为提取出来的公共行为,如果没有默认方法,就需要在所有实现类上修改,保证其完整实现其接口。
# Java8 抽象类与接口
java 8 的接口都有实现方法了,跟抽象类还有什么区别?其实还是有的,请看下表对比。
相同点 | 不同点 |
---|---|
都是抽象类型 | 抽象类不可以多重继承,接口可以 (无论是多重类型继承还是多重行为继承) |
都可以有实现方法 (以前接口不行) | 抽象类和接口所反映出的设计理念不同。其实抽象类表示的是”is-a” 关系,接口表示的是”like-a” 关系 |
都可以不需要实现类或者继承者去实现所有方法,(以前不行,现在接口中默认方法不需要实现者实现) | 接口中定义的变量默认是 public static final 型,且必须给其初值,所以实现类中不能改变其值;抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。 |
# 多重继承冲突
接口可以书写默认方法了,然后又因为接口之间是可以多继承的,因而实质上 Java 8 的接口多继承其实也会涉及到实现多继承的问题。下面我们通过一个实例来看看 Java
它在语法层面的解决方案
interface Father { | |
default void eat() { | |
System.out.println("爸爸吃饭方式..."); | |
} | |
} | |
// 会报错 | |
interface Mother { | |
default void eat() { | |
System.out.println("妈妈吃饭方式..."); | |
} | |
} | |
class Son implements Father, Mother { | |
} | |
// 不报错 | |
class Son implements Father, Mother { | |
@Override | |
public void eat() { | |
System.out.println("儿子自己的吃饭方式~~~"); | |
// 注意这种语法是调用 【指定接口】的 defualt 方法: | |
// 若接口名字没有冲突,直接 super 调用即可~~~ | |
Father.super.eat(); | |
Mother.super.eat(); | |
} | |
} |
当接口的方法前面相同时,才会出现冲突。类中的方法优先级最高。类或者父类中的方法实现优先级大于任何接口的默认方法。如果最后还是无法判断,那么实现类必须通过显示复写方式复写默认方法,再通过 super
调用指定接口的实现。 Java8
在语言层面上,对若出现接口 default
方法冲突的解决方案是:不作为。其实不作为也是一种作为,它让编译器去提示调用者必须显示的 override
这个冲突的方法,让 coder 自己去决定调用逻辑。
其实,更为直白的解释,就是寻找唯一默认方法的最短路径,上述例子,从 Son
实现类找 eat
的实现,从 Son
到 Father
和 Son
到 Mother
距离是一样的,所以会报错。
public interface A{ | |
default void aa() { | |
System.out.println("A's aa"); | |
} | |
} | |
public interface C extends A{ | |
default void aa() { | |
System.out.println("C's aa"); | |
} | |
} | |
public static class D implements C{ | |
} |
从 D
找 aa
方法,从 D
到 C
是最短的。
# 总结
默认方法给予我们修改接口而不破坏原来的实现类的结构提供了便利,目前 java 8 的集合框架已经大量使用了默认方法来改进了,当我们最终开始使用 Java 8 的 lambdas 表达式时,提供给我们一个平滑的过渡体验。也许将来我们会在 API 设计中看到更多的默认方法的应用。
# 参考
Java 全栈知识体系:https://pdai.tech/md/java/java8/java8-default.html#
聊聊 java 中的多继承:https://developer.aliyun.com/article/911510