背景
在Java发展的过程中,接口的演进存在不兼容的问题(即现有实现的类库中不全部是接口的设计者维护升级,不在设计者控制范围之内,如果贸然新增接口方法,其实现类也必须实现新增的方法,这显然是不科学的),故Java不得不做出必要的改进。默认方法(Default Method)便是因此而出现,使得Java的接口也可是平滑的升级演进。
默认方法,定义在接口(Interface)中以关键字default修饰,区别于接口中定义的抽象方法,默认方法是具有实现的方法。示例如下:
public interface Api {
default void hello() {
System.out.println("Hello Default Method!")
}
}
多继承
具有默认方法的接口虽然解决了Java升级过程中的向后兼容问题,但是新的问题也随之出现。那就是臭名昭著的菱形继承问题,C++程序员一定对这个东西不陌生。多个具有相同的方法签名的方法,在继承过程中的选择问题。Java 8的默认方法也不可避免的需要解决它。
在Java8中默认方法的继承遵循以下三原则:
-
如果接口与普通类同时存在以类中的实现为准(类的优先级高于接口)
-
如果接口存在继承关系以子接口中的实现为准(子接口的优先级高于父接口)
-
如果不满足以上两点,需要子类自己实现,如果不实现编译不通过
简而言之,Java8的默认方法继承,取决于更具体的方法实现。
Demo 示例
public class InheritDemo {
interface Parent {
default void run() {
System.out.println("Parent's Run!");
}
}
interface Parent2 {
default void run() {
System.out.println("Parent2's Run!");
}
}
interface Son1 extends Parent {
@Override
default void run() {
System.out.println("Son1's Run!");
}
}
static class Son2 implements Parent {
@Override
public void run() {
System.out.println("Son2's Run!");
}
}
// 满足第2条
static class Child1 implements Son1, Parent {}
// 满足第1条
static class Child2 extends Son2 implements Son1 {}
// 编译报错
static class Child3 implements Parent, Parent2 {}
// 编译通过,满足第3条
static class Child4 implements Parent, Parent2 {
@Override
public void run() {
System.out.println("Child implementation!");
}
}
public static void main(String[] args) {
new Child1().run();
new Child2().run();
}
}
注释掉编译报错的Child3实现,可得运行结果:
Son1's Run!
Son2's Run!
Child implementation!
网友评论