3.6 方法引用
方法引用可以复用现有的方法传递,可读性更好。
inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
inventory.sort(Comparator.comparing(Apple::getWeight));
3.6.1 管中窥豹
方法引用通过显式指明方法名称,创建Lambda表达式。
语法为目标引用::方法名称,注意方法没有包括,因为没有实际调用,例如Apple::getWeight。
Lambda及其等效方法引用示例
Lambda | 等效的方法引用 | 类别 |
---|---|---|
(Apple a) -> a.getWeight() | Apple::getWeight | 指向类型的实例方法 |
() -> Thread.currentThread().dumpStack() | Thread.currentThread()::dumpStack | 指向对象的实例方法 |
(str, i) -> str.substring(i) | String::substring | 指向类型的实例方法 |
(String s) -> System.out.println(s) | System.out::println | 指向类型的实例方法 |
方法引用类别及示例主要有三类:
方法引用类别 | 函数描述符 | 示例 | 方法引用 | 示例 |
---|---|---|---|---|
指向静态方法 | (args) -> ClassName.staticMethod(args) |
(String s) -> Integer.parseInt(s) |
ClassName::staticMethod |
Integer::parseInt |
指向类型实例方法 | (arg0, rest) -> arg0.instanceMethod(rest) |
(String s) -> s.length() |
ClassName::instanceMethod |
String::length |
指向对象实例方法 | (args) -> expr.instanceMethod(args) |
() -> "123".length() |
expr::instanceMethod |
"123"::length |
特殊形式的方法引用:
- 数组构造函数视为指向静态方法的方法引用,例如int[]::new;
- 构造函数视为指向静态方法的方法引用,例如Integer::new;
- 父类调用视为指向对象示例方法的方法引用,例如super::hashCode;
注意:方法引用与Lambda表达式一样,函数描述符必须与上下文类型匹配。
测验3.6:方法引用
下列Lambda表达式的等效方法引用是什么?
-
Function<String, Integer> stringToInteger = (String s) -> Integer.parseInt(s);
stringToInteger = Integer::parseInt;
-
BiPredicate<List<String>, String> contains = (list, element) -> list.contains(element);
contains = List::contains;
,类型推断出String
3.6.2 构造函数引用
对于现有的构造函数,基于类名和关键字new来构造函数引用:ClassName::new。示例详见特殊形式的方法引用的第2点。
构造函数参数个数 | 函数描述符 | 示例 | 方法引用 | 示例 | 函数式接口 | 示例 |
---|---|---|---|---|---|---|
0 | () -> new ClassName() |
() -> new Apple() |
ClassName::new |
Apple::new |
Supplier<ClassType> |
Supplier<Apple> |
1 | (arg0) -> new ClassName(arg0) |
(Integer weight) -> new Apple(weight) |
ClassName::new |
Apple::new |
Function<Arg0Type, ClassType> |
Function<Integer, Apple> |
2 | (arg0, arg1) -> new ClassName(arg0, arg1) |
(String color, Integer weight) -> new Apple(color, weight) |
ClassName::new |
Apple::new |
BiFunction<Arg0Type, Arg1Type, ClassType> |
BiFunction<String, Integer, Apple> |
构造函数引用的写法相同,取决于赋值的函数式接口,对于3个及以上的构造参数,自定义函数式接口。
测验3.7:构造函数引用
已经看到了如何将有零个、一个、两个参数的构造函数转变为构造函数引用。那要怎么样才能对具有三个参数的构造函数,比如Color(int, int, int),使用构造函数引用呢?
自定义一个函数式接口,接收3个参数,返回1个结果,泛型定义参数类型。
public interface TriFunction<T, U, V, R> {
R apply(T t, U u, V v);
}
// invoke
TriFunction<Integer, Integer, Integer, Color> colorFactory = Color::new;