编写Java方法引用的简明方法?

时间:2017-08-18 15:37:22

标签: java functional-programming java-8 method-reference

给出了一些Java 8方法函数:

class Foo { Bar getBar() {} }
class Bar { Baz getBaz() {} }

两个访问者的组合如下:

Function<Foo, Bar> getBarFromFoo = Foo::getBar;
Function<Bar, Baz> getBazFromBar = Bar::getBaz;
Function<Foo, Baz> getBazFromFoo = getBarFromFoo.andThen(getBazFromBar);

有更简洁的方法吗?这似乎有效

((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz)

但它相当难看。由于优先原因,外部的parens是有意义的,但为什么演员必要?

Foo::getBar::getBaz会很好,但唉......)

5 个答案:

答案 0 :(得分:10)

让我们定义一个功能界面:

@FunctionalInterface
interface MyFunctionalInterface {
    Bar getBar(Foo f);
}

我们可以简化方法参考Foo::getBar

(Foo foo) -> foo.getBar();

表示“接受Foo并返回Bar。对于该描述,许多方法都是合适的(例如,我们与getBar的接口和Funtion<Foo, Bar>apply的接口):

MyFunctionalInterface f1 = (Foo foo) -> foo.getBar();
Function<Foo, Bar> f2 = (Foo foo) -> foo.getBar();

这就是为什么演员必要的问题的答案。

为了回答肯定是否有更简洁的方式的问题,我们必须设定一个背景。上下文明确地为我们提供了Function继续使用:

class Functions {
    public static <I, O> Function<I, O> of(Function<I, O> function) {
        return function;
    }
}

Functions.of(Foo::getBar).andThen(Bar::getBaz);

答案 1 :(得分:3)

除了andThen()之外,没有专门的Java编写函数的方法。

您需要执行转换,因为Foo::getBar不明确。 **它可以匹配具有类似方法签名的每个接口。

不幸的是,((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz)是您能做的最好的事情。

答案 2 :(得分:1)

也许只使用lambda表达式?

x -> x.getBar().getBaz()

由于类型歧义,除了你已经提出的功能之外,没有其他方法来组合函数。这甚至不比Foo::getBar::getBaz

长得多

答案 3 :(得分:0)

这是你将获得的最好成绩。如果您认为这样可行:

Foo::getBar::getBaz

它不会。这是因为Foo::getBar多元表达式 - 它取决于所使用的上下文 - 它可能是Function,但也可能是Predicate例如;因此它可能适用于许多事情,所以演员阵容在那里是必要的。

你可以隐藏一个可以进行链接和andThen的方法,但问题仍然存在。

修改

请参阅此处的示例:

public static void cool(Predicate<Integer> predicate) {

}

public static void cool(Function<Integer, String> function) {

}

表达式cool(i -> "Test");将无法编译

答案 4 :(得分:0)

通过Guava,您可以使用Functions.compose

import com.google.common.base.Functions;

...

Functions.compose(Bar::getBaz, Foo::getBar);