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 ...
随机推荐
- public static void main(String[] args) 是什么意思?
public static void main(String[] args),是java程序的入口地址,java虚拟机运行程序的时候首先找的就是main方法. 一.这里要对main函数讲解一下,参数S ...
- 【CodeForces - 707B】Bakery(思维水题)
Bakery Descriptions 玛莎想在从1到n的n个城市中开一家自己的面包店,在其中一个城市烘焙松饼. 为了在她的面包房烘焙松饼,玛莎需要从一些储存的地方建立面粉供应.只有k个仓库,位于不同 ...
- 安装cinder
在控制节点上安装 备注:安装cinder时,nova-compute创建虚拟机时会默认使用cinder指定的存储方式,所以,如果你还要使用本地存储的话,请先参考我这边文章进行设置: 配置nova-co ...
- Attention is all you need 详细解读
自从Attention机制在提出之后,加入Attention的Seq2Seq模型在各个任务上都有了提升,所以现在的seq2seq模型指的都是结合rnn和attention的模型.传统的基于RNN的Se ...
- vue-cli3 取消eslint 校验代码 真正的解决办法
在网上找了各种办法都没解决,看了下文档就解决了 关闭vue-cli3.0 报错:eslint-disable-next-line to ignore the next line. 注意我这里是VU ...
- ZOJ Problem Set - 1007
1.参考这个吧,一道数学公式题,还没看懂...好像需要把公式变形出来,先略过. http://dengbaoleng.iteye.com/blog/1504940
- jumpserver跳板机(堡垒机)安装
jumpserver跳板机(堡垒机) Jumpserver 是一款由Python编写开源的跳板机(堡垒机)系统,实现了跳板机应有的功能,基于ssh协议来管理,客户端无需安装agent,助力互联网企业 ...
- Web循环监控Java调用 / Java调用.net wcf接口
背景介紹 (Background Introduction) 目前有一些报表客户抱怨打不开 报表执行过程过长,5.8.10秒甚至更多 不能及时发现和掌握服务器web站点情况 用戶需求(User Req ...
- java集合List解析
作为一个Developer,Java集合类是我们在工作中运用最多的.最频繁的类.相比于数组(Array)来说,集合类的长度可变,更加适合于现代开发需求: Java集合就像一个容器,可以存储任何类型的数 ...
- 小记--------maxwell启动失败解决
查看报错日志信息: com.github.shyiko.mysql.binlog.network.ServerException: Could not find first log file name ...