Java 8 的这个新特性,用起来真的很爽
文章插图
作者 | 小明菜市场
来源 | 小明菜市场(ID:fileGeek)
头图 | CSDN 下载自东方IC
文章插图
前言从一道面试题说起
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.默认方法名这种方式进行调用 。
- 智能手机市场|华为再拿第一!27%的份额领跑全行业,苹果8%排在第四名!
- 会员|美容院使用会员管理软件给顾客更好的消费体验!
- 行业|现在行业内客服托管费用是怎么算的
- 人民币|天猫国际新增“服务大类”,知舟集团提醒入驻这些类目的要注意
- 国外|坐拥77件专利,打破国外的垄断,造出中国最先进的家电芯片
- 长安|长安傍上华为这个大腿,市值暴涨500亿!可见华为影响力之大?
- 技术|做“视频”绿厂是专业的,这项技术获人民日报评论点赞
- 面临|“熟悉的陌生人”不该被边缘化
- 中国|浅谈5G移动通信技术的前世和今生
- 手机|这个超强App,让手机快3倍,流畅到起飞