java8中接口新特性_介绍一个Java8的新特性,接口增强

从一道面试题说起

A: 接口里可以写方法吗?

B: 可以的,默认就是抽象方法。

A: 那接口里可以写实现方法吗?

B: 不可以,所有的方法必须是抽象的。

A: 你确定?

B: 确定。。。。

好吧。这的的确确让人有点怀疑,所以本文就从这开始着手,

这里介绍一个Java8的新特性,接口增强

静态方法和默认方法

我们可以在Comparator接口的源码中,看到大量类似下面这样的方法声明。

//default关键字修饰的默认方法

default Comparator thenComparingInt(ToIntFunction super T> keyExtractor) {

return thenComparing(comparingInt(keyExtractor));

}

//Comparator接口中的静态方法

public static > Comparator naturalOrder() {

return (Comparator) Comparators.NaturalOrderComparator.INSTANCE;

}

其中thenComparingInt()就是一个默认方法,它使用 default 关键字修饰。这是Java8引入的新功能,接口中的可以声明默认方法和静态方法。

默认方法带来的多继承问题

在此之前,Java中的类只支持多重继承,不支持多继承,现在有了默认方法,你可以以另外一种方式实现类的多继承行为,即,一个类实现多个接口,而这几个接口都有声明自己的默认方法。

这里面引发了一个多继承问题,设想一下,假如一个类从多个接口中继承了它们声明的默认方法,而这几个默认方法使用的都是相同的函数签名,那么程序运行时,类会选择调用那个方法

第一份代码

@Test

public void test2() {

new C().hello();//result: hello from D

}

interface A {

default void hello() {

System.out.println("heelo from A");

}

}

interface B extends A {

default void hello() {

System.out.println("heelo from B");

}

}

class D implements A{

public void hello() {

System.out.println("hello from D");

}

}

class C extends D implements A, B{

}

这份代码输出的结果是 hello from D,可以看到 C 类的父类D,父接口A,父接口B都定义了一个相同函数签名的hello(),最后实际调用的是父类D中声明的方法。

第二份代码

@Test

public void test4() {

new I().hello();//result: heelo from G

}

class I implements G, H { }

interface G extends E {

default void hello() {

System.out.println("heelo from G");

}

}

interface H extends E { }

interface E {

default void hello() {

System.out.println("heelo from E");

}

}

代码清单二的输出结果是 hello from G,可以看到 I 类的父接口 G,父接口E都定义了一个相同函数签名 hello(),最后实际调用的是父类接口G中声明的方法。

第三份代码

@Test

public void test3() {

new F().hello(); //result: heelo from E

}

interface A {

default void hello() {

System.out.println("heelo from A");

}

}

interface E {

default void hello() {

System.out.println("heelo from E");

}

}

class F implements A, E {

public void hello() {

//这里接口A和E不再具有继承关系,需显式的选择调用接口E或A中的方法,否则无法通过编译            E.super.hello();

}

}

第三份代码,类F必须显式的覆盖父接口的hello方法,否则无法通过编译器的检测,因为编译器无法确定父接口A和父接口E中的默认方法哪一个优先。

这种情况下,如果你想调用某个父接口的默认方法,可以使用 接口名.super.默认方法名这种方式进行调用。

总结

Java8的新特性: 接口中可以声明默认方法和静态方法。

另外,接口默认方法带来的多继承问题,即,如果一个类使用相同的函数签名从多个地方继承了方法,通过这三种规则可以判断类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。

如果无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,优先选择有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体。

最后, 如果还是无法判断, 继承了多个接口的类必须通过显式覆盖和调用期望的方法, 显式地选择使用哪一个默认方法的实现(调用语法: 接口名.super.默认方法名 )。

想系统学习Java的可以关注我的视频哦,持续更新哈!9291a7f44e707b918d0cc9b8953b6ef3.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值