Java8新特性default关键字,引出Java多继承问题
概述
最近在看JDK集合的源码时,在Collection接口中发现了default关键字,并且惊奇的发现接口中的方法居然包含方法体,这顿时让我产生兴趣,为此我也稍微研究了一下default关键字。
很多同学都知道Java在创立之初就摒弃了C++多继承的套路,因为它实在难以学习与使用,在Java的世界中类只能继承一个父类,但是一个接口可以继承多个接口,就比如这样:
public interface A {
void hello();
}
public interface B {
void hello();
}
public interface C extends A,B {
}
但是Java8的新特性也使得Java也拥有了多继承的问题,想要了解的小伙伴就继续往下看吧。
引入default关键字
大家都知道Java中的接口都是抽象方法,也就是没有方法体,但是从Java8开始,如果接口中的方法被default关键字修饰后就必须为其加上方法体。某个类在实现该接口时,就不会强制实现被default修饰的方法,因为在接口中已经写好了方法体。从Java8开始,接口就开始类似于抽象类了,它们都可以含有普通方法和抽象方法了,唯一不同的就是一个类只能继承一个抽象类,而一个类却能实现多个接口。
default关键字示例:
public interface A {
default void sayHello(){
System.out.print("A.Hello");
}
}
default关键字的意义:default关键字的意义,default的意思就是为接口方法提供默认的实现,它的最终目的就是减少子类实现接口的工作量,,如果多个子类实现的某个接口方法,方法体都是一样的,这就会导致后期维护上的困难,如果在接口中定义默认的实现,那么既减少了子类实现的接口的工作量,也为后期的维护提供了方便(只需要更改接口中的默认实现即可)。
多继承问题的引入
但是default关键字的出现也顺带为java带来了多继承的问题,我现在来举一个栗子:
现有两个接口,A和B,这两个接口都有一个方法sayHello,并且都使用default关键字修饰后使其拥有了方法体,但是现在有接口C需要同时继承A,B,代码如下:
public interface A {
default void sayHello(){
System.out.print("A.Hello");
}
}
public interface B {
default void sayHello(){
System.out.print("B.Hello");
}
}
public interface C extends A,B{
}
此时多继承的问题就展现出来了,到底C接口是继承A接口的sayHello方法,还是继承B接口的sayHello方法,这也就是Java多继承的源头,允许接口有方法体,并且接口之间可以多继承。(上面代码由于有多继承问题,编译会报错!!)
多继承问题的解决
Java给出的解决方案就是:在出现多继承问题的时候必须手动覆写冲突方法,这种方式可谓是简单出爆,但很好理解。手动覆写后编译器就不纠结到底继承哪个父类的方法了,也就解决了多继承问题。
子接口在手动覆写父接口方法时可以手动调用冲突方法,调用格式如下:
public interface A {
default void sayHello(){
System.out.print("A.Hello");
}
}
public interface B {
default void sayHello(){
System.out.print("B.Hello");
}
}
public interface C extends A,B{
@Override
default void sayHello() {
A.super.sayHello();
}
}
public class Test impements A.B {//类的多实现本质上就是多继承
@Override
default void sayHello() {//因为接口A和接口B中的默认方法冲突,所以必须手动实现sayHello方法
A.super.sayHello();
}
}
另一种多继承
public interface A {
default void sayHello(){
System.out.print("A.Hello");
}
}
public interface B extends A{
default void sayHello(){
System.out.print("B.Hello");
}
}
public class Test impements A.B {
}
在上述代码中,接口B继承了接口A,如果Test类实现A,B接口是不存在冲突的,实际上在实际开发中通常也不会这个写,因为既然B继承了A接口,那么在实现的时候直接实现B接口就行了,显示实现A接口没有任何意义。
拓展:Java8的接口可以拥有静态方法
可以参考博主另一篇文章:《Java8新特性——接口静态方法》
走过路过不要错过,原创不易,帮忙点个赞撒!!!!