java8学习之深入函数式接口与方法引用
函数式接口:
函数式接口【FunctionalInterface】是整个Lambda表达式的一个根源,换句话来说java8中的Lambda表达式要想彻底掌握,前提是要彻底理解好函数式接口,所以这次继续对函数式接口进行巩固。
先回顾一下上一次通过读FunctionalInterface这个注解的javadoc之后的三点总结【参考:http://www.cnblogs.com/webor2006/p/8111585.html】:
关于FunctionalInterface的doc上有一个细节还需要注意,在上次中也已经提到过,这里再拧出来看一下:
那换成代码如何来理解上面这段话呢?新建一个接口,里面声明一个方法,当然它是抽象的【抽象的概念是只有声明木有具体实现的】:
那这个是不是FuncationalInterface呢?加上注解就可以论证了:
那如果再增加一个抽象方法:
看下报错提示:
那如果此时将这个新加的方法名称换一个是Object类中的呢?
那为什么呢?原因就如javadoc上面的这点所描述:toString()是一个抽象方法,但是Object中也有此方法,细心的可以发现其实开发工具比较智能的在该方法的左侧已经显示出来一个箭头,点击则可以查看它父类的方法:
那点开看一下呗:
很显然该方法是复写的Object类的中方法,所以java编译器不认为该方法是一个抽象方法,所以当然整个接口还是满足只有一个抽象方法的条件,当然认为此时的接口还是一个函数式接口啦。这是表现上的理论,那为啥要有这样的一个规定呢?其实也比较好理解:如果一个类实现该接口,那很明显该类一定有这两个方法的实现,然而java.lang.Object是所有类的父类,也就是说明具体类都会直接或间接的继承Object类中的方法,而toString()并非是子类特有的方法,所以说如果一个方法中声明的刚好是Object类中的方法,那它不算抽象方法。
接下来继续用代码来进行延深:
由于MyInterface是函数式接口,所以可以改用Lambda表达式,如下:
其实上面标红的Lamdba表达式的写法就是MyInterface的匿名实现类,所以程序可以这样写:
那咱们可以打印一下这个类和它父类名字,如下:
那这个myInterface类的具体实现的接口是哪些呢?接着可以打印一下:
那这接口是谁呢?继续打印:
通过上面的例子对于函数式接口应该有一个比较好的认识了,所以对于它的探讨先暂时到这,接下来对于之前的例子进行一个进一步的探讨,回顾下当时的代码:
通过三种方式来对一个集合进行遍历,这里将重点观注在最后一种用函数式接口的方式,那这个forEach方法是来自于List类中么?点击查看下源码:
来自于Iterable接口当中,可以看到该方法是从Java1.8才开始引入的,但是Iterable是从1.5就开始引入的:
而我们知道List最终是实现了Iterable这个接口,所以当然也就继承有forEach这个方法啦,这就解释了为啥可以通过List去直接调用forEach来达到遍历的目的。
这里需要注意一下细节,这个forEach方法的具体实现实际上就是写在Iterable接口当中的,但是在接口的声明前面有个default关键字,这个也在之前说了,在Java8以后在接口中可以有具体实现了,但凡在接口中有具体实现方法,前面必须加default的关键字,这称之为默认方法(Default Method),而对于实现这个接口的类也自然而然继承有这个默认方法了,有点像抽象类的概念:类中既可有抽象方法,也可以有具体方法,而继承类也会继承抽象类的具体方法。
接着来查看一下forEach javadoc的注释:
接下来再来看一下这个指定的动作Consumer,从字面意思来理解当然就是消费者的意思啦,点击看一下它的源码:
读一下接口的doc:
再回到咱们的程序来说,很显然可以换成Lambda表达式来改造,所有函数式接口都可以采用Lambda表达式来编写,如下:
下面再对Lambda表达式进行一个总结。
Lambda表达式作用:
- Lambda表达式为Java添加了缺失的函数式编程特性,使得我们能将函数当做一等公民对待。
因为Java在以前方法永远都是依附于类而存在的,不可以独立存在的, 现在我们可以将方法当作参数进行传递了, 所以函数在Java8里面就成了一等公民。 - 在将函数作为一等公民的语言中,Lambda表达式的类型是函数,但在Java中,Lambda表达式是对象,他们必须依咐于一类特别的对象类型---函数式接口(Functional Interface)
标红的说Lambda表达式是对象,为什么呢?
迭代方式:
外部迭代:
什么是外部迭代呢?看程序:
下面用图来更形象的理解:
然后一个个元素进行迭代,最后指向一个空的元素既迭代完成了,如下:
内部迭代:
何为内部迭代,直接看代码:
之所以叫内部迭代,相对于外部迭代,当然是没有了外部迭代的迭代器啦,不借助于外部力量既完成元素的迭代。
方法引用:
对于上面元素迭待的方式已经改用Lambda表达式去写,代码已经很精简了,但是!!还可以更加精简,如下:
对于上面这种写法就叫做方法引用(method references),而这个forEach方法参数是函数式接口的实例,那意思是这个方法引用能创建函数式接口的实例?是的,在查看函数式注解的javadoc上就已经清楚的说明了,这里再来回顾一下:
这里看一个IDE比较智能的地方,就是在方法引用语句中的"::"处点击ctrl键之后会看到:
自动就跳到了Consumer这个函数式接口了,说明编译器识别到了这种定法就是对Consumer接口的实现,关于方法引用在之后还会仔细学习,这里有个感性的认识就行。
java8学习之深入函数式接口与方法引用的更多相关文章
- Java8 Lambda表达式、函数式接口和方法引用
目录 Java8 Lambda表达式和函数式接口 Lambda表达式 Lambda的使用 函数式接口FunctionalInterface Java内置四大核心函数式接口 方法引用 构造器引用 Jav ...
- 009-jdk1.8版本新特性一-展方法,Lambda表达式,函数式接口、方法引用构造引用
一.JDK1.8 名称:Spider(蜘蛛) 发布日期:2014-03-18 新特性: 1.1.扩展方法[接口的默认方法] Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 defaul ...
- java8学习之BiFunction函数式接口实例演示&Predicate函数式接口详解
BiFunction函数式接口: 在上次中已经对BiFunction接口进行了初步的认识,这里对它进一步学习,这里打算新建一个Person实体,然后新建若干个Person的实例存放在集合中,最后再根据 ...
- JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用
jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default Lambda表达式 L ...
- 乐字节-Java8新特性之函数式接口
上一篇小乐带大家学过 Java8新特性-Lambda表达式,那什么时候可以使用Lambda?通常Lambda表达式是用在函数式接口上使用的.从Java8开始引入了函数式接口,其说明比较简单:函数式接口 ...
- Java8新特性之函数式接口
<Java 8 实战>学习笔记系列 定义 函数式接口只定义一个抽象方法,可以有多个默认方法 函数式接口的接口名上,会被@FunctionalInterface标注 作用 函数式接口的方法可 ...
- Lambda学习总结(一)--函数式接口
Lambda 表达式是 JDK 1.8 里面的一个重要更新,这意味着 Java 也开始承认了函数式编程,并且尝试引入其中,我们今天就来了解下它的使用. 一.函数式接口 1.1 概念 函数式接口在 Ja ...
- Java8一Lambda与函数式接口
关于Lambda表示在工作学习中会经常用到,但并没有全面的去了解.在这里做一个较为详细的记录供以后学习查阅.主要参考Java 8 Lambda 表达式 引言 Java8之前,我们在使用Runnale创 ...
- Java8内置的函数式接口
JDK 1.8 API 包含了很多内置的函数式接口.其中就包括我们在老版本中经常见到的 Comparator 和 Runnable,Java 8 为他们都添加了 @FunctionalInterfac ...
随机推荐
- LeetCode.1175-质数排列(Prime Arrangements)
这是小川的第413次更新,第446篇原创 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第264题(顺位题号是1175).返回1到n的排列数,以使质数处于质数索引(索引从1开始).(请 ...
- kubeadm安装集群系列-5.其他操作
常用的一些操作记录 imagePullSecrets kubectl -n [namespace] create secret docker-registry regsecret --docker-s ...
- Leetcode之动态规划(DP)专题-714. 买卖股票的最佳时机含手续费(Best Time to Buy and Sell Stock with Transaction Fee)
Leetcode之动态规划(DP)专题-714. 买卖股票的最佳时机含手续费(Best Time to Buy and Sell Stock with Transaction Fee) 股票问题: 1 ...
- C学习笔记-预备知识
计算机结构组成 CPU(中央处理器)(控制器+运算器) 存储器(内存+外存) 输出设备 输入设备 计算机系统组成 硬件系统 主机 中央处理器 运算器 控制器 内存储器 只读存储器 随机存储器 外部设备 ...
- js放到head中失效的原因与解决方法
1.今天写js碰到一个奇怪的问题,写好的js放到body里面执行,但是放到head中没有任何效果,为什么导致这种原因呢? 看失效代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
- Linux文件属性改变命令chown-chgrp-chattr-lsattr实践
chown 语法: chattr.lsattr 更改文件属性
- Centos7 安装python3.8和pip
安装python3 yum -y install yum-utilsyum-builddep pythoncurl -O https://www.python.org/ftp/python/3.8.0 ...
- Linux 防火墙设置常用指令
查看防火墙状态命令: service firewalld status systemctl status firewalld 结果: 其中: enabled:开机启动(开机不启动是disabled ...
- Vue里标签嵌套限制问题解决------解析DOM模板时注意事项:
受到html本身的一些限制,像<ul>.<ol>.<table>.<select>这样的元素里允许包含的元素有限制,而另一些像<option> ...
- PAT B1015A1062德才论(25)
题目描述 宋代史学家司马光在<资治通鉴>中有一段著名的"德才论":"是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人.凡取人之术,苟不得 ...