Java 8 Lambda 表达式详解
一、Lambda 表达式
1、基础语法
Lambda 表达式基础语法:
(parameters) -> expression
或 (parameters) ->{ statements; }
先理解:这段代码可理解为一个方法,小括号里的内容是方法入参,大括号里的内容是方法体。 而这行代码,就是一个 Lambda 表达式。所以 Lambda 表达式实际是一个方法(即函数)。
Java 8 中规定:Lambda 允许把函数(即Lambda 表达式)作为一个方法的参数(类似 JS 中的闭包)。 所以:Lambda 表达式是一个对象,而这个对象实际是一个方法。所以,Lambda 表达式是一个方法对象。
但是到底是什么对象呢?这个后续再细说。
2、语法简写形式
既然是一个方法,那么对自然有一些简写形式,如下:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。 即()里面无需声明参数类型。()里面甚至可以什么都没有
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。 即()可以省略。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。 即{}可以省略,同时语句后面的分号也可以省略。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
就是说,小括号中的入参可省略,小括号可省略,大括号可省略,大括号中的内容还可省略。 注:小括号和小括号中的入参不能同时省略。怎么省略可详细参考:Java 8 Lambda 表达式 | 菜鸟教程
3、其他语法注意:
lambda 表达式只能引用标记了 final 的外层局部变量。即不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。 注:修改final肯定会报错。另外,基本类型final就是final,引用类型final只表示变量地址(即引用)不可变,变量指向的内容还是实际可变的。
可以在 lambda 表达式中直接访问外层的局部变量: 注:final肯定可以被直接引用了。
lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义) 注:这点应该由编译来保证。即在lambda 表达式内部使用的局部变量肯定为final,即使不显式声明。
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。 注:这点肯定是的。同名肯定会出错。
二、方法引用和Lambda的关系
2.1 什么是方法引用?
方法引用是 lambda 表达式的一种特殊形式,即方法引用就是 Lambda 表达式(方法引用是 lambda 表达式的一种语法糖)。
方法引用用于获取一个已有方法的 Lambda 表达式形式。
上面两句应该说明了什么是方法引用。
2.2 方法引用的使用语法和限制
注:大写开头表示类名,小写开头表示对象。
引用静态方法 ContainingClass::staticMethodName 例子: String::valueOf,对应的 Lambda:(s) -> String.valueOf (s) 比较容易理解,和静态方法调用相比,只是把.换为::
引用特定对象的实例方法 containingObject::instanceMethodName 例子: x::toString,对应的 Lambda:() -> this.toString () 与引用静态方法相比,都换为实例的而已
引用特定类型的任意对象的实例方法(不建议使用,比较麻烦) ContainingType::methodName 例子: String::toString,对应的 Lambda:(s) -> s.toString () 实例方法要通过对象来调用,方法引用对应 Lambda,Lambda 的第一个参数会成为调用实例方法的对象。
引用构造函数 ClassName::new 例子: String::new,对应的 Lambda:() -> new String () 构造函数本质上是静态方法,只是方法名字比较特殊。
注意:第一和第三的区别在于::
后面的方法是静态还是非静态,其他一致。
参考:Java 8 之方法引用 (Method References) - 永无止境,上下求索 - CSDN 博客
三、功能接口
3.1 功能接口定义
上面,一直说Lambda 表达式是一个对象,那是什么类型的对象呢? 这个类型就是功能接口类型。
在 Java 中,功能接口(Functional interface)指只有一个抽象方法的接口。 即如果一个接口只有一个抽象方法,Java 会自动认为该接口是功能接口。同时,该接口可以作为 Lambda 表达式的对象类型。 所以:Lambda 表达式是功能接口类型的对象,但这个功能接口类型不只一个,而是一类,这点要注意。
这里分析一下:Lambda 表达式既是方法(实现),又是对象。是什么方法(实现)?功能接口的方法(实现)。是什么类型接口的对象?功能接口类型的对象。 到这里,一切就清晰了。
那如何确定一个接口是不是功能接口呢?
可以用
@FunctionalInterface
注解标识。如果被标识的接口不符合功能接口规则,那么是会编译报错的。
3.2 JDK 中已有的功能接口
首先:这 4 个接口都是功能接口,所以其只有一个抽象方法。而这 4 个接口的不同在于抽象方法的参数和返回结果不同。理解了这点,就看也理解这四个接口了。
Function.java
主要方法:R apply(T t);
功能说明: 将 Function 对象应用到输入的参数上,然后返回计算结果。Consumer.java
主要方法:void accept(T t);
功能说明: 该接口表示接受单个输入参数并且没有返回值的操作。Predicate.java
主要方法:boolean test(T t);
功能说明: 表示判断输入的对象是否符合某个条件。Supplier.java
主要方法:T get();
功能说明: 无参数,返回一个结果。
总结一下上面的4个接口的区别:
接口 | 参数 | 返回结果 |
---|---|---|
Function | 有 | 有 |
Consumer | 有 | 无 |
Predicate | 有 | 布尔类型 |
Supplier | 无 | 有 |
参考:JDK8 函数式接口 Function、Consumer、Predicate、Supplier - 酒肉猿 - CSDN 博客
四、使用实例:
参考:例子可参考:Java 8 Lambda 表达式详解 - 程序员干货 - SegmentFault 思否 到这里,你应该就知道可以怎么用了。
五、Stream API 与 Lambda 表达式
Stream API是JDK8的一个新特性,和 Lambda 的关系在于其可以接受 Lambda 表达式参数,使代码更加简洁方便。 具体使用可参考 JDK 文档:Java 8 中文版 - 在线 API 中文手册 - 码工具 中的Interface Stream<T>
这里面有常用的map,sort等方法的接口声明。
至于 Stream 的更详细的知识,后续再写。暂时只写Lambda。
常用功能和方法说明:
六、参考:
Lambda 表达式有何用处? - FACEBOOK THEM - CSDN 博客 注:特别优秀的一篇教程,很棒。
Java 8 Lambda 表达式详解的更多相关文章
- Java中lambda表达式详解
原文地址:http://blog.laofu.online/2018/04/20/java-lambda/ 为什么使用lambda 在java中我们很容易将一个变量赋值,比如int a =0;int ...
- JAVA8之lambda表达式详解
原文:http://blog.csdn.net/jinzhencs/article/details/50748202 lambda表达式详解 一.问题 1.什么是lambda表达式? 2.lambda ...
- Java8 Lambda表达式详解手册及实例
先贩卖一下焦虑,Java8发于2014年3月18日,距离现在已经快6年了,如果你对Java8的新特性还没有应用,甚至还一无所知,那你真得关注公众号"程序新视界",好好系列的学习一下 ...
- Lambda表达式详解(例子详解)(转自:http://blog.csdn.net/damon316/article/details/51734661)
Lambda表达式详解(例子详解) lambda简介 lambda运算符:所有的lambda表达式都是用新的lambda运算符 " => ",可以叫他,“转到”或者 ...
- 类型:.net;问题:C#lambda表达式;结果:Lambda表达式详解
Lambda表达式详解 前言 1.天真热,程序员活着不易,星期天,也要顶着火辣辣的太阳,总结这些东西. 2.夸夸lambda吧:简化了匿名委托的使用,让你让代码更加简洁,优雅.据说它是微软自c#1 ...
- Java lambda 表达式详解(JDK 8 新特性)
什么是 lambda 表达式 lambda 表达式(拉姆达表达式)是 JAVA 8 中提供的一种新的特性,它使 Java 也能进行简单的"函数式编程". lambda 表达式的本质 ...
- java8 lambda 表达式详解
lambada 表达式实质上是一个匿名方法,但该方法并非独立执行,而是用于实现由函数式接口定义的唯一抽象方法 使用 lambda 表达式时,会创建实现了函数式接口的一个匿名类实例 可以将 lambda ...
- Lambda表达式详解
前言 1.天真热,程序员活着不易,星期天,也要顶着火辣辣的太阳,总结这些东西. 2.夸夸lambda吧:简化了匿名委托的使用,让你让代码更加简洁,优雅.据说它是微软自c#1.0后新增的最重要的功能之一 ...
- C# Lambda表达式详解,及Lambda表达式树的创建
最近由于项目需要,刚刚学完了Action委托和Func<T>委托,发现学完了委托就必须学习lambda表达式,委托和Lambda表达式联合起来,才能充分的体现委托的便利.才能使代码更加简介 ...
随机推荐
- Memcached 教程
http://www.runoob.com/memcached/memcached-tutorial.html
- ubuntu彻底干净卸载MySQL、Apache2、Php的方法(各版本通用
一.卸载删除 mysql 1 sudo apt-get autoremove --purge mysql-server-5.0 2 sudo apt-get remove mysql-server ...
- Mysql的replace into语句
Mysql语句 replace into 跟 insert 功能类似,不同点在于:replace into 首先尝试插入数据到表中, 1. 如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删 ...
- C语言 fork
/* *@author cody *@date 2014-08-12 *@description */ /* #include <sys/types.h> #include <uni ...
- Atitit.进程管理常用api
Atitit.进程管理常用api 1 常用api 进程列表 getProcessList 是否存在某个进程判断 isExistProcess 启动进程run Sleep Exit Shutdown 作 ...
- POJ--3529--Wormholes
Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 36889 Accepted: 13520 Descr ...
- (WPF)依赖属性
属性触发器: <Button MinWidth=" 75" Margin="10"> <Button.Style> <Style ...
- 1.文件I/O
一. open()&close() #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h& ...
- Java遍历包中所有类
PackageUtil 类 import java.io.File; import java.net.URL; import java.net.URLClassLoader; import java. ...
- 李洪强iOS开发之iOS技术博客
李洪强iOS开发之iOS技术博客 注意:访问博客请直接点击博客,不要点击后面的RSS地址 博客地址 RSS地址 南峰子的技术博客 剑尖博客 图拉鼎 Henry Lee Dev Talk ...