Java中的Lambda表达式

Lambda表达式可以理解为简洁地表达可传递的匿名函数的一种方式。

他没有名称,但是有参数列表、函数主体、返回类型,还可以抛出异常

可传递:Lambda表达式可以作为参数传递给方法或存储在变量中

Lambda表达式语法格式如下

(参数1, 参数2 ... ) -> {主体代码}

Lambda语法有几个特点:

  • 类型声明可省略:参数的类型可省略,编译器可自动识别
  • 参数圆括号可省略:一个参数可以省略圆括号,无参或多个参数需要圆括号
  • 大括号可省略:如果主体部分只是一个语句,可以省略大括号
  • 返回关键字可省略:如果主体只有一个表达式返回值,则可以省略返回关键字编译器会自动返回,如果多条语句则不能省略

函数式接口

函数式接口 == 有且仅有一个抽象方法的接口

lambda表达式可以直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例。

使用匿名类也可以完成同样的事,但是比较笨拙。

Java中函数式接口前常使用 @FunctionalInterface来标记,但这不是必须的,只要接口满足只存在一个抽象方法即可。

我们可以自己定义函数式接口,但通常情况下,如果需要的函数式接口没有其他的方法的话,格式是比较固定的。JDK已经为我们定义好了一些支持泛型的函数式接口,足以满足大部分的需要。如Runnable、Supplier、Consumer、Function

函数式接口变量引用lambda表达式

//Function是JDK提供的一个支持泛型的函数式接口
Function 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表达式中声明一个与局部变量同名的参数或局部变量是不合法的。

Original: https://www.cnblogs.com/shiruyanhai/p/16117718.html
Author: 诗如沿海
Title: Java中的Lambda表达式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/608008/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球