Java 8方法参考

时间:2017-04-03 22:01:23

标签: java java-8

在Java 8中,是否可以连续调用2个引用方法?

customer::new::getName

可以连接2种方法参考形式:

a::b::c

3 个答案:

答案 0 :(得分:3)

如何内联两个方法引用表达式?

让我们分解Customer::new::getName表达式;

T1 customer = Customer::new;
T2 name = customer::getName; 

根据JLS描述的方法参考表达式,因此T1T2必须为FunctionalInterface

  

如果T是函数接口类型(第9.8节)且表达式与地面目标类型的函数类型一致,则方法引用表达式在赋值上下文,调用上下文或具有目标类型T的转换上下文中是兼容的源自T。

Supplier<Customer>T1一起使用时,编译器会报告错误:无法解析在供应商上定义的方法getName 。但您可以定义自己的FunctionalInterface,例如:CustomerSupplier

interface CustomerSupplier {
    Customer get();

    default String getName() {
        return get().getName();
    }
}

然后您可以将Customer::new推荐给CustomerSupplier

CustomerSupplier customer = Customer::new;
Supplier<String> name = customer::getName;

实际上,您可以进一步将两个表达式内联在一起,但每个方法引用表达式必须是FunctionalInterface,因此您必须将Customer::new强制转换为CustomerSupplier

Supplier<String> customerName = ((CustomerSupplier) Customer::new)::getName;

然而,最简单的就是直接访问@Holger提供的内容。

Supplier<String> customerName = () -> new Customer().getName();

如何链接两个方法引用表达式?

由于Supplier没有组合FunctionInterface的方法,但您可以像这样链接方法引用表达式:

interface Reference<T> extends Supplier<T> {
    static <T> Reference<T> of(Supplier<T> reference) {
        return reference::get;
    }

    default <R> Reference<R> of(Function<T, R> after) {
        return () -> after.apply(get());
    }
}

//NOTE:Reference is derived from Supplier, so it is compatible with Supplier.  
Supplier<String> customerName = Reference.of(Customer::new).of(Customer::getName);

但是,您可以引入一种方法来避免引入用于组合@Holger提供的函数接口的类型。

private <T, R> Supplier<R> map(Supplier<T> target, Function<T, R> mapper) {
    return () -> mapper.apply(target.get());
}

Supplier<String> customerName = map(Customer::new, Customer::getName);

答案 1 :(得分:1)

不,您无法链接两个方法引用。

基本上,方法引用是一种语法糖,它允许您将现有方法的定义传递给Lambda表达式(实现单abstract方法)。

答案 2 :(得分:1)

  

在Java 8中,是否可以连续调用2个引用方法?

不,在使用方法引用时链接方法是不可能的,因为方法引用本质上是执行 ONE 方法的lambda表达式的简写语法。因此,一旦开始链接方法,它将不再是方法引用的有效语法。

<强>语法

Object::methodName