给出了一些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
会很好,但唉......)
答案 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);