zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Java Lambda表达式:一旦学会就回不去了,谁用谁知道

JAVA 知道 学会 表达式 lambda 一旦
2023-06-13 09:15:37 时间
原文链接:https://dzone.com/articles/java-lambda-expressions-functions-as-first-class-c

作者:Yogen Rai

译者:helloworldtang

自Java 8发布以来,许多样板代码都可以使用Lambda表达式替代。我真的想在Java中发表一篇关于 的文章,但是如果我们能将流与Lambda表达式结合起来,那么就肯定会带来真正的价值。因此,我就先写一下如何使用Lambda表达式。

函数式接口

一个函数式接口是指一个接口只有一个抽象方法,也称为SAM (Single Abstract Method)【单一的抽象方法】类型。这个概念是在JDK 8中引入的,但是在JDK 8之前就已经有接口符合该定义了。例如, Comparator接口就只有一个抽象方法: compare()

我们可以自定义函数式接口:

@FunctionalInterface
interface Calculator<T,R> {
    R calculate(T a, T b);
}

在这里, @FunctionalInterface注解由编译器检查。因此,如果该接口不是仅仅只包含一个抽象方法,那么就会出现编译错误。

温馨提示: 包括0个或多个抽象方法都会编译错误

在为Lambda表达式自定义函数式接口时,可以不使用这个注解,但是,像其他注解(例如 @Override)一样,使用 @FunctionalInterface是最佳实践,因为该注解会告诉编译器需要检查这个函数式接口是否有效——否则,这个函数式接口的合法性检查将被忽略,直到实际运行的时候。

那么,什么是Lambda表达式呢?

Lambda表达式是函数式接口的内联实现,可以替代某些匿名内部类。

Lambda表达式由三部分组成:

Lambda参数列表 [一个或多个]
    ->
代码块 [如果多于一个语句,需要用花括号括起来{...} ] 
      [可以包含自由变量;自由变量的值由本地变量或实例变量提供]

温馨提示: 自由变量:在Lambda表达式作用域之外定义的变量

例如:

(a,b) -> a + b; //传入两个数字类型的参数a和b,返回另一个数字:两个入参相加的结果
(String str) -> System.out.println(str); //在控制台打印传入的字符串

上例中,第一个Lambda表达式的等价形式如下所示:

new Calculator<Integer, Integer>() {    
    @Override    
    public Integer calculate(Integer a, Integer b) {        
        return a + b;    
    }
};

通过对比,您可以看到Lambda表达式是如何帮助我们去除样板代码的。

命名Lambda表达式

Java中的每一个对象都有一个类型;Lambda表达式也是如此。Lambda表达式的类型可以是任何一个函数式接口,其中Lambda表达式是具体的值。

命名Lambda表达式是通过使用适当的函数式接口作为其类型,就像命名任何一个普通对象一样。例如:

Calculator<Integer, Integer> adder = (a,b) -> a + b;

上例中,Lambda表达式的名字是 Calculator类型的 adder

温馨提示: 此处我们省略了参数类型,因为如果可以推断出参数类型,就可以省略。

带上参数类型的Lambda表达式如下所示:

Calculator<Integer, Integer> adder = (Integer a,Integer b) -> a + b;

如何使用Lambda表达式

现在,您可以看到Lambda表达式几乎取代了匿名内部类,因为它具备了内部类的基本功能特性:映射到返回值。因此,函数现在是一等公民了。所以:

  1. Lambda表达式可以像正常的类实例一样来调用自己的方法。例如, adder可以直接调用 calculate方法:
Integer sum = adder.calculate(3,4); // sum = 7

2. Lambda表达式可以作为参数传递给方法,并用于方法内的表达式:

// ...
printSum(adder);
// ...
static void printSum(Calculator cal) {
    System.out.println(cal.calculate(4,5));
}

3. Lambda表达式可以作为返回值返回:

// ...
Calculator<Integer, Integer> multiplier = getCalculatorFunc();
Integer result = multiplier.calculate(6,9));  // 54
// ...
static Calculator getCalculatorFunc() {
    Calculator<Integer, Integer> multiplier = (a, b) -> a * b;
    return multiplier;
}

总结

现在,您可以看到如何在维护Java语言面向对象特性的同时,又从函数式编程中获得了好处。Lambda表达式是使用Stream进行函数式编程和编写简洁代码的基础,我将在下一篇文章中继续介绍。直到那时,我们就可以快乐地编码了!

像往常一样,文中用到的代码可以在GitHub上找到。