Java中的lambda表达式
前言:异步的文章中,线程的创建用到了
lambda
表达式,作为 JDK 8的新特性同时也是函数式编程的代表实践,趁此机会学习一下
一、函数式编程思想概述
在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作”
面向对象思想强调“必须通过对象的形式来做事情”
函数式思想则强调尽量忽略面向对象的复杂语句:“强调做什么,而不是以什么形式去做”
而接下来要讲的Lambda表达式就是函数式思想的体现
二、Lambda 表达式基础
1. 为什么要使用 Lambda 表达式
这里还是以创建执行一个线程举例,有以下三种方式
方式1,使用传统方式创建新对象:
- 定义一个类MyRunnable接口,重写run方法
- 创建MyRunnable类的对象
- 创建Thread类对象,把MyRunnable的对象作为构造参数传递
- 启动线程
1 |
|
1 |
|
方式2,在方式1的基础上做改进,使用匿名内部类:
1 |
|
方式3,使用lambda做进一步简化:
1 |
|
通过以上三种方式,相信你已经看出来了,lambda表达式能使代码轻量化,极大地优化代码结构,它只关心入参和方法体(即做事的逻辑),其他的(返回类型,参数类型,方法名)都不关心。
2. Lambda 表达式的标准格式
Lambda表达式的代码分析
格式:
(形式参数...) -> {代码块}
()
:包含方法的入参,里面若没有内容,可以看成是方法形式参数为空;若只有一个入参,可以省略()
->
:用箭头指向后面要做的事情{}
:包含一段代码,我们称之为代码块,可以看成是方法体中的内容;若只有一行内容,可以省略{}
、;
,有返回值可以省略return
Lambda表达式使用示例
需先定义一个接口,包含一个加法的抽象方法:
1 |
|
定义外部方法调用接口:
1 |
|
调用外部方法,以lambda表达式替代传入的接口对象
1 |
|
Lambda表达式的注意事项
使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象的方法
必须有上下文环境,才能推导出Lambda对应的接口
- 根据局部变量的赋值得知Lambda对应的接口:
1 |
|
- 根据调用方法的参数得知Lambda对应的接口:
1 |
|
3. Lambda表达式和匿名内部类的区别
所需类型不同
- 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
- Lambda表达式:只能是接口
使用限制不同
如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
实现原理不同
- 匿名内部类:编译之后,产生一个单独的.class字节码文件
- Lambda表达式:编译之后,没有一个单独的.class字节码文件,对应的字节码会在运行的时候动态生成
参考文章: Java 函数式编程
Java中的lambda表达式
http://dunkingcurry30.github.io/2022/07/12/lambda表达式/