死磕Lambda表达式(三):更简洁的Lambda
万猫学社 人气:6
>我们都是阴沟里的虫子,但总还是得有人仰望星空。——《三体》
在之前的文章中介绍了Lambda表达式的[基本语法](https://mp.weixin.qq.com/s/ce85WnptSOyQaMBep8L_oA)和[正确使用姿势](https://mp.weixin.qq.com/s/wW1IWOIxKR_LU0Rf-TaxtA),这次我来介绍一些Lambda更简洁的用法。
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
### 类型推断
编译器可以通过函数式接口推断出Lambda表达式的参数类型,所以在编写Lambda表达式时,可以省略参数类型。比如:
```java
Comparator comparator = (Mask o1, Mask o2) -> o1.getBrand().compareTo(o2.getBrand());
```
就可以简写为:
```java
Comparator comparator = (o1, o2) -> o1.getBrand().compareTo(o2.getBrand());
```
另外,当Lambda表达式只有一个参数的时候,不仅可以省略参数类型,还可以省略到参数名称两边的括号,比如:
```java
Predicate predicate = (Mask mask) -> mask.getType() == "N95";
```
就可以简写为:
```java
Predicate predicate = mask -> mask.getType() == "N95";
```
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
### 方法引用
#### 什么是方法引用?
方法引用是Java8中引入的新特性,它提供了一种引用方法而不执行方法的方式,可以让我们重复使用现用方法的定义,做为某些Lambda表达式的另一种更简洁的写法。
比如前面的例子:
```java
Comparator comparator = (o1, o2) -> o1.getBrand().compareTo(o2.getBrand());
```
使用方法引用以后,可以简写为:
```java
Comparator comparator = Comparator.comparing(Mask::getBrand);
```
当你需要方法引用时,目标引用放在分隔符`::`前,方法的名称放在分隔符`::`后。比如,上面的`Mask::getBrand`,就是引用了`Mask`中定义的`getBrand`方法。方法名称后不需要加括号,因为我们并没有实际调用它。方法引用提高了代码的可读性,也使逻辑更加清晰。
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
#### 怎么构建方法引用?
可以构建方法引用的场景的有四种:
##### 1. 静态方法
指向静态方法的引用,语法:`类名::静态方法名`,类名放在分隔符`::`前,:静态方法名放在分隔符`::`后。比如:
```java
(String str) -> Integer.parseInt(str)
```
使用方法引用以后,可以简写为:
```java
Integer::parseInt
```
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
##### 2. 内部对象的实例方法
指向Lambda表达式内部对象的实例方法的引用,语法:`类名::实例方法名`,类名放在分隔符`::`前,:实例方法名放在分隔符`::`后。比如:
```java
(Mask mask) -> mask.getBrand()
```
使用方法引用以后,可以简写为:
```java
Mask::getBrand
```
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
##### 3. 外部对象的实例方法
指向Lambda表达式外部对象的实例方法的引用,语法:`实例名::实例方法名`,类名放在分隔符`::`前,:实例方法名放在分隔符`::`后。比如:
```java
String type = "N95";
Predicate predicate = (String str) -> type.equals(str);
System.out.println(predicate.test("N95"));
```
其中,`type`是一个Lambda表达式外部的局部变量,使用方法引用以后,可以简写为:
```java
String type = "N95";
Predicate predicate = type::equals;
System.out.println(predicate.test("N95"));
```
如果对于`Predicate`接口还不熟悉,没关系,以后的文章会介绍到,这里暂且知道它的抽象方法的签名是`(T) -> boolean`就可以了。
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
##### 4. 构造方法
指向构造方法的引用,语法:`类名::new`,类名放在分隔符`::`前,`new`放在分隔符`::`后。比如:
```java
(String brand, String type) -> new Mask(brand, type)
```
使用方法引用以后,可以简写为:
```java
Mask::new
```
#### 小测试
看了这么多,是不是摩拳擦掌准备试一试了?我们就来一个小测试:
1. `(char[] array) -> new String(array)`
2. `(String str) -> str.length()`
3. `(String type) -> mask.setType(type)`,其中的`mask`是一个`Mask`对象的局部变量。
4. `(String str) -> System.out.println(str)`
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
请思考片刻…
.
.
.
![](https://img-blog.csdnimg.cn/20200103185150176.jpg)
.
.
.
**宣布答案**:
1. 因为`(char[] array) -> new String(array)`是一个构造方法的Lambda表达式,此种方法引用的语法是:`类名::new`,所以正确答案是:`String::new`。
2. 因为`(String str) -> str.length()`是一个内部对象的实例方法的Lambda表达式,此种方法引用的语法是:`类名::实例方法名`,所以正确答案是:`String::length`。
3. 因为`(String type) -> mask.setType(type)`中的`mask`是一个`Mask`对象的局部变量,它是一个包含外部对象的Lambda表达式,此种方法引用的语法是:`实例名::实例方法名`,所以正确答案是`mask::setType`。
4. 因为`(String str) -> System.out.println(str)`是一个静态方法的Lambda表达式,此种方法引用的语法是:`类名::静态方法名`,所以正确答案是`System.out::println`。
怎么样?都答对了嘛?
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
### 《死磕Lambda表达式》系列
- [死磕Lambda表达式(一):初识Lambda](https://mp.weixin.qq.com/s/ce85WnptSOyQaMBep8L_oA)
- [死磕Lambda表达式(二):Lambda的使用](https://mp.weixin.qq.com/s/wW1IWOIxKR_LU0Rf-TaxtA)
- [死磕Lambda表达式(三):更简洁的Lambda](https://mp.weixin.qq.com/s/wVlVabABtiLmhmf8WNbyHQ)
- [死磕Lambda表达式(四):常用的函数式接口](https://mp.weixin.qq.com/s/5u2P9QFJJ1wR-yT46ysuig)
- [死磕Lambda表达式(五):Comparator复合](https://mp.weixin.qq.com/s/AFu_fOFct5kgurIub8MCNw)
- [死磕Lambda表达式(六):Consumer、Predicate、Function复合](https://mp.weixin.qq.com/s/CGO59kUQxrngOjthI_3OCQ)
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
加载全部内容