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

特殊形式的方法引用:

  1. 数组构造函数视为指向静态方法的方法引用,例如int[]::new;
  2. 构造函数视为指向静态方法的方法引用,例如Integer::new;
  3. 父类调用视为指向对象示例方法的方法引用,例如super::hashCode;

注意:方法引用与Lambda表达式一样,函数描述符必须与上下文类型匹配。

测验3.6:方法引用

下列Lambda表达式的等效方法引用是什么?

  1. Function<String, Integer> stringToInteger = (String s) -> Integer.parseInt(s);

    stringToInteger = Integer::parseInt;

  2. 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;
posted @ 2023-06-28 17:44  夜是故乡明  阅读(12)  评论(0编辑  收藏  举报