目录
Lambda 表达式在实际开发中主要目的往往是用来简化匿名内部类的书写。我们知道,有些方法中的参数需要传递接口的实现类对象,假如说我们为了传递类对象而单独去创建一个类,会显得代码有些冗余,所以这个时候我们往往会采用匿名内部类的形式去创建接口的实现类对象。
那么此时,我们将一段逻辑代码作为参数放到方法的参数列表中,会显得不那么好看,所以为了简化代码量,让参数列表更简洁好看,我们就可以采用 Lambda 表达式的方式来书写匿名内部类。
我先来展示一段匿名内部类的代码逻辑,如下
我随便定义了一个数组,添加几个乱序的数,现要对它们进行排序,我可以调用 Arrays 中的 sort 方法排序,该方法传递两个参数,第一个参数传递要排序的数组,第二个参数传递一个比较器对象。
- public class LambdaTest {
- public static void main(String[] args) {
- // 定义一个数组
- Integer[] arr = {1,4,8,0,9,6,7};
- // 调用 Array 中的 sort 方法对数组中的数据排序,
- Arrays.sort(arr, new Comparator
() { - // 重写方法逻辑
- @Override
- public int compare(Integer o1, Integer o2) {
- return o1 - o2;
- }
- });
- System.out.println(Arrays.toString(arr));
- }
- }
那么问题来了,比较器接口 Java 已经提供了,但它没有提供实现类,怎么办呢?我们能在 Java 源码中实现 Comparator 接口吗?这种做法显然是不可行的,所以这个时候我们就可以采用匿名内部类的形式,创建一个 Comparator 接口的实现类对象,并做相应的逻辑处理。
运行上述代码,我们就可以在控制台得到如下结果,可以发现数组已经排好序了。
Lambda 表达式的格式非常简单,我们只需要将原本匿名内部类方法中的参数写入到 "()" 中,将方法的执行逻辑写入 "{}" 即可,中间使用固定格式 "->" 连接即可。
使用 Lambda 表达式将上面匿名内部类的代码简化之后,就变成了下面这个样子。
可以看到,在使用了 Lambda 表达式之后,代码变得极为简介,删掉了方法名,@Override注解,还删掉了一对大括号,只留下方法的参数和方法的执行逻辑。
我们再次运行此方法,仍然可以在控制台得到正确的结果,这就是 Lambda 表达式的简单使用。
在使用 Lambda 表达式简化匿名内部类的书写时,需要注意两个点。
(1)Lambda 表达式主要用于简化匿名内部类的书写,一般不应用于其他地方;
(2)并不是所有的匿名内部类都可以使用 Lambda 表达式来简化书写,它只能简化函数式接口的匿名内部类的书写方式。
记住一句话就可以了,"有且仅有一个抽象方法的接口叫函数式接口,接口上可以添加@FunctionalInterface注解"。
例如我们刚才使用的 Compartor 接口,它就是一个函数式接口,我们看一下它的源码就可以知道,如下图所示,接口上就标注有 @FunctionalInterface 注解。
通过上面的学习,我们已经简单的了解明白了如何使用 Lambda 表达式简化函数式接口的匿名内部类写法。
但我现在告诉你,尽管 Lambda 表达式已经上面已经非常简化了,其实在一些情况下,Lambda 表达式本身的写法还可以继续省略,但在省略时需要满足以下几点规则。
(1)参数类型可以省略不写;
(2)如果只有一个参数,参数类型省略不写,同时 "()" 也可以省略;
(3)如果 Lambda 表达式的方法体只有一行,大括号,分号,returen 同时省略不写,注意是三个同时省略不写。
基于上面的省略要求,我们还可以对上面排序的代码继续简化,我们先把原本的 Lambda 代码拿过来,如下图
第一步:
先看第一点,参数类型省略不写,省略之后如下所示
第二点:
上述方法中两个参数,所以 "()" 不能省略,不做变化
第三点:
方法体只有一行,"return","{}",";" 同时省略不写,就会变成下面这个样子
此时我们在运行此方法,仍然可以在控制台得到正确的运行结果,如下图
有些同学可能会觉得这样写可读性太差了,也很正常,等我们运用熟练了就习惯了。
这里我还是要补充一句,Lambda 表达式的使用在开发中还是较为常见的,所以同学们还是要重视起来,在以后的一些项目中,你还是有可能经常会见到 Stream 流搭配 Lambda 表达式结合使用简化代码的,所以在我们遇到的时候要能看得懂。