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新特性——接口静态方法》

走过路过不要错过,原创不易,帮忙点个赞撒!!!!

 

posted @ 2018-12-30 14:18  听到微笑  阅读(3)  评论(0编辑  收藏  举报  来源