各位读者好, 我是小陈, 这是我的个人主页
小陈还在持续努力学习编程, 努力通过博客输出所学知识
如果本篇对你有帮助, 烦请点赞关注支持一波, 感激不尽
希望我的专栏能够帮助到你:
JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等
Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等
JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议, Tomcat, Servlet, Linux, JVM等(正在持续更新)
由于正在更新 Java【EE初阶】部分中多线程相关的文章,lambda表达式 是多线程编程中很常用的语法功能,本篇将分享 lambda表达式 相关的内容, 主要介绍 lambda表达式 的使用方式 以及在集合中的一些应用
如果看到这篇文章的读者们正处于 Java 基础语法阶段,只要有【类和对象、接口】部分的基础就可以无压力学会 lambda表达式 的基本操作
提示:是正在努力进步的小菜鸟一只,如有大佬发现文章欠佳之处欢迎评论区指点~ 废话不多说,直接发车~
Lambda表达式 是 JavaSE8 中一个重要的新特性。lambda表达式 允许你通过表达式来代替功能接口(函数式接口)。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)
Lambda 表达式(Lambda expression),基于数学中的λ演算得名,也可称为闭包(Closure)
要学习 lambda表达式,要先了解一下什么是函数式接口
函数式接口 : 一个接口中有且仅有一个抽象方法(不能存在方法体)
例如 多线程编程中提到的 Runnable接口 的源码 :
这就是一个函数是接口, 可以看到, 接口中只有一个抽象方法, 并且还有一个注解 : @FunctionalInterface
这个注解负责说明 : 这是一个函数式接口, 并且负责检查 : 如果这个接口中还有其他方法, 就会编译不通过
JDK1.8 新增规定: 可以额外定义 default 方法(但是必须写出方法体)
我们自己写一个函数式接口试试 :
如果写了两个抽象方法, @FunctionalInterface 这个注解就会帮我们检查出来并报错
基本语法: (parameters) -> { statements ; } 或者写成 : (parameters) -> expression
一个 lambda表达式 由三部分组成:
1️⃣paramaters :类似方法中的形参列表,这里的参数是函数式接口里的参数, 数据类型可以声明, 也可以不声明
当只有一个参数时, 可以省略小括号
2️⃣-> :可理解为 “被用于” 的意思
3️⃣方法体 :代码块(一行或多行), 是函数式接口里方法的实现 , 可以有返回值也可以没有, 等同于方法的方法体
当只有一句代码块时, 可以省略大括号和分号
以下仅展示语法使用和效果, 并不是完整的使用方式,具体使用下面会演示
// 1. 无参, 返回值为 2
() -> {2;}
// 2. 有一个参数x(省略类型), 返回参数x的二倍
x -> {2 * x;}
// 3. 有两个参数x, y(省略类型), 返回x+y的和
(x, y) -> {x + y;}
// 4. 有两个参数x, y, 返回x+y的积
(int x, int y) -> {x * y;}
// 5. 有一个参数s, 类型为String, 执行打印操作, 无返回值
(String s) -> {System.out.print(s);}
举 6 个例子, 能够覆盖所有的使用场景 :
1️⃣无参, 无返回值
2️⃣有一个参, 无返回值
3️⃣有多个参, 无返回值
4️⃣无参, 有返回值
5️⃣有一个参, 有返回值
6️⃣有多个参, 有返回值
所以接下来会定义 6 种函数式接口
复习知识点 : 要调用接口里的方法, 就需要有一个类实现这个接口, 在这个类中重写接口中的抽象方法, 然后实例化这个类, 才能调用
我们先展示最原始的写法:
1️⃣先定义出 NoParameterNoReturn 接口
2️⃣定义一个类 A , 实现 NoParameterNoReturn 接口, 并重写其中的 test 方法
3️⃣定义一个对象 “noParameterNoReturn”, 实例化类A
4️⃣调用对象中的 test 方法
控制台打印:
无参无返回值
然后来看匿名内部类的写法 :
实例化了一个不知道叫什么名字的类, 只知道这个类实现了 NoParameterNoReturn 接口, 并重写了其中的抽象方法
以下示例只展示 匿名内部类 及 lambda表达式 的写法
控制台打印:
20: 有一个参, 无返回值
控制台打印:
30: 有多个参, 无返回值
控制台打印 :
无参, 有返回值
100
控制台打印:
20: 有一个参, 有返回值
20
控制台打印:
30: 有两个参, 有返回值
30
以有多个参, 有返回值的接口为例 : 使用函数式接口时 , idea 可以检查并提示你的代码编写方式
不知道读者是否发现了, 匿名内部类方式实现函数式接口时, 实例化对象时, new关键字及后面的接口名是灰色的
原因是idea更推荐你使用 lambda表达式 的写法
如图:
现在大概可以理解了: Lambda表达式 就是匿名内部类的简化,无非就是创建了一个类,实现了接口,重写了接口的方法
匿名内部类 和 lambda表达式 使用时, 有一个需要注意的地方 : 变量捕获
以无参无返回值的接口为例 :
在调用接口中的方法之前, 定义了两个变量 a , b 和一个常量 A , 尝试在方法中捕获 a , b 和 A
控制台打印 ;
a 的值是: 10
b 的值是: 20
A 的值是: 30
A是常量, 不能被修改
, 我们只讨论变量 a , b , 如果更改变量 a, b 的值, 就无法捕捉这两个变量, 直接编译报错, 如图 :
和匿名内部类一致, 只是写法不同, 如果是没有修改过的变量, 或者常量是可以捕获的
控制台打印 ;
a 的值是: 10
b 的值是: 20
A 的值是: 30
各位读者应该可以很直观的感受到 lambda表达式 的优点:代码层次上来说,非常的精简,不止如此,它还有很多优点:
1️⃣代码简洁,如果熟悉函数式接口,将会提高开发效率
2️⃣在多线程编程中方便进行并行运算
3️⃣能够改善集合中的部分操作(集合中提供了很多函数式接口)
这些优点就说明了为什么要有 lambda 表达式,但它也有一些缺点
1️⃣代码可读性下降
2️⃣不容易进行代码调试
对于简单的 lambda 表达式使用起来还是很方便的, 对于可读性和代码调试的打击也不会太大, 但是如果使用复杂的lambda表达式进行编程, 上述两条缺点就会放大, 并且需要程序员对于函数式接口非常的熟悉
以上就是本篇的全部内容啦,主要介绍了:
1,lambda表达式 的语法和使用方法
2,lambda表达式 和 匿名内部类 中的变量捕获
3,lambda表达式 的优缺点
如果本篇对你有帮助,请点赞收藏支持一下,小手一抖就是对作者莫大的鼓励啦~
上山总比下山辛苦
下篇文章见