Java8系列 (四) 静态方法和默认方法(转载)
静态方法和默认方法
我们可以在 Comparator 接口的源码中, 看到大量类似下面这样的方法声明
//default关键字修饰的默认方法
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparingInt(keyExtractor));
}
//Comparator接口中的静态方法
public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>) 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.默认方法名 )。
作者:张小凡
出处:https://www.cnblogs.com/qingshanli/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】。
Java8系列 (四) 静态方法和默认方法(转载)的更多相关文章
- Java8系列 (四) 静态方法和默认方法
静态方法和默认方法 我们可以在 Comparator 接口的源码中, 看到大量类似下面这样的方法声明 //default关键字修饰的默认方法 default Comparator<T> t ...
- 乐字节-Java8核心特性实战-接口默认方法
JAVA8已经发布很久,是自java5(2004年发布)之后Oracle发布的最重要的一个版本.其中包括语言.编译器.库.工具和JVM等诸多方面的新特性,对于国内外互联网公司来说,Java8是以后技术 ...
- Java8新特性——接口的默认方法和类方法
Java8新增了接口的默认方法和类方法: 以前,接口里的方法要求全部是抽象方法,java8以后允许在接口里定义默认方法和类方法: 不同的是: 默认方法可以通过实现接口的类实例化的对象来调用,而类方法只 ...
- java8新特性——接口中的静态方法与默认方法
以前我们知道,接口中的方法必须时抽象方法,而从 java8 开始接口中也可以有方法的实现了,叫做默认方法. 一 .默认方法(default修饰) 在 java8 中,因为存在函数式接口,一个接口中只能 ...
- Java8新特性-接口中的静态方法与默认方法
今天上午在读<Effective Java>时,有这样一句话:”接口中“不能有静态方法,于是联想起面试时老是被问接口相关的东西,决定总结一下,谁知道这一总结,就发现了自己知识的一大漏洞. ...
- Java8简明学习之接口默认方法
接口中有默认方法实现Java8允许我们使用default关键字,为接口声明添加非抽象的方法实现. public interface DefaultInterFace { int plus(int x, ...
- JDK8新特性:接口的静态方法和默认方法
在jdk8之前,interface之中可以定义变量和方法,变量必须是public.static.final的,方法必须是public.abstract的.由于这些修饰符都是默认的,所以在JDK8之前, ...
- java8之lambda表达式(默认方法)
[推荐]2019 Java 开发者跳槽指南.pdf(吐血整理)>>> 许多开发语言都将函数表达式集成到了其集合库中.这样比循环方式所需的代码更少,并且更加容易理解.以下面的循环为例: ...
- jdk8系列一、jdk8 Lamda表达式语法、接口的默认方法和静态方法、supplier用法
一.简介 毫无疑问,Java 8是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和JVM等方面的十多个新特性. 在本文中我们将学习这些新特性,并用实际 ...
随机推荐
- 常见Http状态码大全详解
HTTP状态码的分类 HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用.HTTP状态码共分为5种类型: 具体如下: 状态码 内容 详细内容 信息告知 - ...
- Tensorflow机器学习入门——MINIST数据集识别(卷积神经网络)
#自动下载并加载数据 from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_s ...
- 吴裕雄--天生自然HADOOP操作实验学习笔记:qq好友推荐算法
实验目的 初步认识图计算的知识点 复习mapreduce的知识点,复习自定义排序分组的方法 学会设计mapreduce程序解决实际问题 实验原理 QQ好友推荐算法是所有推荐算法中思路最简单的,我们利用 ...
- Python学习第七课——集合(set) 和 字符串拼接
集合(set) # 2 无序 # 3 集合中元素必须是不可变类型 # 定义集合 s = {1,2,3,4,5} print(s) # 输出结果 {1, 2, 3, 4, 5} # 1 集合由不同元素组 ...
- Linux centos7 awk工具
一.awk介绍 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk含盖sed所有功能,把文件逐行的读入,以空格为默认分隔 ...
- 第二章:windows下搭建开发环境
IDE ---- pycharm数据库 --- mysql.redis.elasticsearch开发环境 -- anaconda 第一节:pycharm的安装和简单使用...(网上一搜一大堆,所以没 ...
- Day9 - I - 不要62 HDU - 2089
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍, ...
- 单词统计——基本Java实现(无特殊设置)
日期:2019.5.4 博客期:066 星期六 今天写了统计一篇文章中的单词数量,把出现最多的前几个显示出来,差不多就是这么个程序! 实现思想: 分布处理: 1.读取文件,将文件里的字符串按照换行符和 ...
- hibernate通过数据库表反向生成实体类
步骤一: window-->open Perspective-->MyEclipse Java Persistence 进行了上面的 操作后会出现一个视图DB Brower:MyEcl ...
- 复习hibernate
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. Hibernate可以应用在任何使用JDB ...