例如,如果我有这样的界面:
public interface FooBar<A, B> {
B foo(A a);
B bar(A a);
}
有没有办法采用像FooBar::bar
这样的类级方法引用并获取实例方法引用?
即。如果我有
FooBar myFooBarInstance;
BiFunction<FooBar<A, B>, A, B> barFunction = FooBar::bar;
是否有任何简单的方法可以获得一个Function<A,B>
实例,该实例与我定义的内容相匹配
Function<A, B> myBarFunction = myFooBarInstance::bar;
答案 0 :(得分:7)
您想要做的是在函数编程领域中称为“部分函数应用程序”,或者在功能较少的术语中将“将值绑定到参数”。没有内置的方法,但很容易编写自己的方法:
public static <T,U,R> Function<U,R> bind(BiFunction<T,U,R> f, T t) {
return u -> f.apply(t, u);
}
然后你可以在你的情况下使用它:
FooBar<X,Y> instance=…;
BiFunction<FooBar<X,Y>,X,Y> barFunction=FooBar::bar;
Function<X,Y> myBarFunction=bind(barFunction, instance);
或只是
// equivalent to myBarFunction=instance::bar
Function<X,Y> myBarFunction=bind(FooBar::bar, instance);
请注意,实用程序方法对于您正在使用的功能接口(即Function
和BiFunction
)是紧密的,而不是方法引用。它适用于任何BiFunction
,可以实现为方法引用,lambda表达式或普通类。但是只有当你特别需要一个Function
实例时才会有用,而不是一个带有一个参数的任意函数接口。您可以使用Function
将::apply
转换为另一个单参数函数类型,但使用bind(bifunc, value)::apply
在需要实例的地方不会比x -> bifunc.apply(value, u)
提供任何好处。
因此,如果您必须经常通过绑定第一个参数将BiFunction
转换为Function
,则实用程序方法可能很有用。否则,只需在存在实际目标类型的上下文中使用lambda表达式。当然,你也可以为其他接口编写一个类似的方法,但是如果你经常需要它用于那个特定的接口,这将再次有用。
关于采用更多参数的函数,由于Java API不提供这样的功能接口,您必须自己定义适当的接口,这提供了在接口中直接提供绑定功能的选项default
方法,例如
interface MyFunc3<A,B,C,R> {
R apply(A a, B b, C c);
default BiFunction<B,C,R> bind(A a) {
return (b, c) -> apply(a, b, c);
}
}
interface MyFunc4<A,B,C,D,R> {
R apply(A a, B b, C c, D d);
default MyFunc3<B,C,D,R> bind(A a) {
return (b, c, d) -> apply(a, b, c, d);
}
}
然后,如果你有像
这样的功能MyFunc4<U, W, X, Y, Z> func = …;
你可以做点什么
MyFunc3<W, X, Y, Z> f3 = func.bind(u);
或
BiFunction<X, Y, Z> f2 = func.bind(u).bind(w);
答案 1 :(得分:3)
我意识到,一旦我想到答案,答案就非常简单了。我可以这样做:
Function<A, B> instanceFunction = (a)->barFunction.apply(myFooBar, a);
如果你的方法需要多于几个参数,那真的很难看,但它有效......