Java中的Lambda表达式
Java中的Lambda表达式
Lambda表达式可以理解为简洁地表达可传递的匿名函数的一种方式。
他没有名称,但是有参数列表、函数主体、返回类型,还可以抛出异常
可传递:Lambda表达式可以作为参数传递给方法或存储在变量中
语法
Lambda表达式语法格式如下
(参数1, 参数2 ... ) -> {主体代码}
Lambda语法有几个特点:
- 类型声明可省略:参数的类型可省略,编译器可自动识别
- 参数圆括号可省略:一个参数可以省略圆括号,无参或多个参数需要圆括号
- 大括号可省略:如果主体部分只是一个语句,可以省略大括号
- 返回关键字可省略:如果主体只有一个表达式返回值,则可以省略返回关键字编译器会自动返回,如果多条语句则不能省略
函数式接口
函数式接口 == 有且仅有一个抽象方法的接口
lambda表达式可以直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例。
使用匿名类也可以完成同样的事,但是比较笨拙。
在Java中函数式接口前常使用@FunctionalInterface来标记,但这不是必须的,只要接口满足只存在一个抽象方法即可。
我们可以自己定义函数式接口,但通常情况下,如果需要的函数式接口没有其他的方法的话,格式是比较固定的。JDK已经为我们定义好了一些支持泛型的函数式接口,足以满足大部分的需要。如Runnable、Supplier
函数式接口变量引用lambda表达式
//Function<T, R>是JDK提供的一个支持泛型的函数式接口
Function<Integer, String> fun = number -> {
return "the number is : " + number;
};
Lambda的使用
- 行为参数化:lambda表达式主要使用场景就是作为参数传递给某个方法,以便在该方法在适当的时间执行这个lambda的代码。
- 函数式接口传递行为:如果我们想传递一个lambda给一个方法,那该方法的参数就声明为对应的函数式接口类型,因为lambda表达式可以赋值给对应的函数式接口类型的对象。
- 执行行为:函数式接口类型的对象引用一个lambda表达式,该lambda实际上就是实现了该函数式接口的抽象方法,因此若想执行lambda的行为,可以直接调用该函数式接口对象的抽象方法即可。
//Runnable是一个JDK自带的函数式接口,Fun方法使用函数式接口对象作为参数,传递行为
public static void Fun(Runnable r) {
//执行行为,当然我们可以等到某个时刻或者某个事件再执行
r.run();
}
public static void main(String[] args) {
//行为参数化,将lambda表达式作为参数传递给Fun方法
Fun(() -> {
System.out.println("line1");
System.out.println("line2");
});
}
方法引用
将现有的方法作为lambda表达式。
编写lambda表达式时,可能已经有现成的方法可以满足我们的需求。那我们可以直接把这个现成的方法当作lambda表达式,这就是方法引用。例如
Timer time = new Timer(1000, event -> System.out.println(event));
//可以写为
Timer time = new Timer(1000, System.out::println);
方法的引用有三种形式:
- object::instanceMethod
- Class::staticMethod
- Class::instanceMethod
分别等价于
- (x) -> object::instanceMethod(x)
- (x) -> Class::staticMethod(x)
- (x, y) -> x.Class::instanceMethod(y)
自由变量
指嵌套lambda表达式的代码块中定义的局部变量
lambda表达式的数据结构必须存储自由变量的值,称之为捕获。捕获的自由变量有一个限制,必须是实际上值不变的变量(可以不加final限定,只要值不变就行)。不论是lambda代码块外还是代码块中,被捕获的自由变量的值都不允许改变。
局部变量保存在栈上,如果lambda直接访问外部块的局部变量,lambda代码体真正被执行时局部变量可能已经被回收(lambda常常作为回调,所以一般不会立刻执行)。所以lambda都会保存一个自由变量的副本。如果自由变量允许改变,造成外部代码块中以及每个lambda表达式之间的自由变量值不同步。
变量作用域
lambda表达式代码块与嵌套lambda表达式的代码块有相同的作用域,因此在lambda表达式中声明一个与局部变量同名的参数或局部变量是不合法的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)