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表达式联合起来,才能充分的体现委托的便利.才能使代码更加简介 ...
随机推荐
- 基于DDD的.NET开发框架-DDD经典分层
DDD核心思想是由业务问题来控制解决方案的形式从以数据库为中心过渡到领域模型为中心 下面这个图是我在<领域驱动设计与模式实战>书中拍下来的,他完全诠释DDD的经典分层. 程序代码中也是响应 ...
- Heap 3214 LIS题解
依据问题转换成最长不降子序列问题. 10^9的输入数据计算起来还是挺花时间的.由于这里仅仅能使用O(nlgn)时间复杂度了. 只是证明是能够算出10^9个数据的. 由于时间限制是5s. #includ ...
- Tokyo Tyrant(TTServer)系列(六)-数据丢失谁的错
,false,1,100);$mem->addServer ("127.9.9.1",1978,false,1,100);$start=microtime(true);for ...
- 多线程-ThreadPoolExecutor
线程池 线程池是可以控制线程创建.释放.并通过某种策略尝试复用线程去执行任务的一种管理框架,从而实现线程资源与任务之间的一种平衡. 类图 Executor Executor是最基本的执行接口:“执行者 ...
- atitit.js的 字符串内容 转义 js处理html
atitit.js的 字符串内容 转义 js处理html 1. js处理html的问题 1 2. js的 字符串内容 转义 1 2.1. 处理流程 1 3. 下面的表格列出了其余的特殊字符,这些特殊 ...
- [k8s]k8s-web-terminal配置使用 & etcdui etcd browser配置 & etcdkeeper3配置
安装kube-dns后,我想看看他是怎么个配置,于是我就找到了这个 参考: https://github.com/beyondblog/k8s-web-terminal cat >> /e ...
- [svc]msmtp+mutt发附件,发邮件给多个人
环境:centos6.7 x86-64 内网有web服务器(curl可展示目录) #预安装软件 yum install lrzsz ntpdate sysstat dos2unix wget teln ...
- C# asp.net页面常用语法,页面包含
搞.net开发这么多年,知道和用过包含include指令吗? <%@ Page Language="C#" AutoEventWireup="true" ...
- todos Vue
<div id="todo-list-example"> <input v-model="newTodoText" v-on:keyup.en ...
- telnet master主机的NodePort服务不通的问题
硬件环境: 两台物理机: 172.16.114.210(master主机) 172.16.114.211(node主机) 软件环境: kubernetes 1.5.2 flannel 0.5.5 问题 ...