Java Lambda从入门到精通二 lambda到底是什么

上一节我们看了lambda的效果,你可能还看不懂lambda,我们这一节就讲解到底lambda是什么。

Lambda表达式的语法

lambda表达式分为三部分:参数、分隔符、表达式。

以我们上一节的苹果过滤lambda为例:

(Apple a) -> a.weight >150

() 括号括起来的是表达式的参数

-> 将参数和表达式分隔开

a.weight >150 就是表达式,其中表达式可以是一个语句块用{}括起来,例如:

(int i) -> {
    System.out.println("当前入参 :"+i);
    System.out.println("计算结果哦 :"+i+1);
}

lambda到底是什么呢?

在Java中,lambda就是函数式接口的抽象方法的具体实现,并且这个实现的书写简单易用。如果你不用lambda,也可以像第一节的改进版方案,为每一种逻辑都写一个处理类(策略模式),在需要时调用不同的处理类,同样也可以得到想要的结果。

使用lambda的好处就是不必创建这些策略类了,代码减少了,也变得简洁、易读、优雅了,更重要的是,能让我们的代码更加灵活,可以轻松应对多变的需求和复杂的场景。

那么什么是函数式接口呢?

Java中如果一个接口中有且只有一个抽象方法,那么这个接口就是函数式接口,也可以用注解@FunctionalInterface声明在类上。不声明也是可以的,只要保证接口只有一个抽象方法,加上这个注解的好处是,如果你担心你定义的函数式接口类在以后被不知道的人添加了其他抽象方法,而导致报错,那么就加上这个注解。

怎样写出正确的lambda表达式?

我们写的lambda表达式,并不是想怎么写就怎么写。我们所写的任何lambda表达式,都要有对应的函数式接口的抽象方法与之对应。也就是说lambda的入参和返回值,要和函数式接口的抽象方法定义的入参和返回值相匹配。只有有对应的函数式接口抽象方法,才能使用对应的lambda表达式。

我们上一节,定义了一个苹果的抽象类AppleFormatter,我们现在加上注解,将其显示声明为函数式接口。

/**
 * @Auther: www.itzhimei.com
 * @Description:
 */
@FunctionalInterface
public interface AppleFormatter {
    String accept(Apple apple);
}

按照上面的逻辑,lambda就是函数式接口的抽象方法的具体实现,我们实现一个判断苹果颜色的lambda:

printApple(apples,(Apple a) -> 
            a.getColor().equals("红") ? "红苹果" : "绿苹果");

这个方法的第二个参数,就是根据AppleFormatter的String accept(Apple apple)方法,定义的lambda表达式,表达式同样声明了入参为Apple,返回值为String。

还有另一种写法,我基于lambda,声明一个AppleFormatter的lambda对象,作为参数传入printApple方法中:

AppleFormatter color = (Apple apple) -> 
            apple.getColor().equals("红") ? "红苹果" : "绿苹果";
printApple(apples,color);

输出结果同样都是:

红苹果
绿苹果
红苹果

总结:我们学习lambda一定要知道,lambda的使用,都是基于函数式接口的抽象方法的。函数式接口的抽象方法就好比是房子的钢筋骨架,定义了房子的整体结构,这个整体结构在代码中就相当于方法的入参和返回类型,更专业的说法是方法签名,而lambda则是房子的外墙,在房子骨架的基础上,进行应用,也就是把房子盖起来,代码中则是按照抽象方法的签名,来使用,使用方式就是遵循抽象方法的入参和返回值。

学习lambda一定要搞清楚上面这段总结的内容,只有理解的这段话,才算真正理解了lambda。

理解了上面这段话,以后使用lambda才能更加灵活自如,而不是只停留在使用一些集合类已经提供的lambda方法。