例如,如果我有这样的界面:
public interface FooBar<A, B> {
B foo(A a);
B bar(A a);
}
Run Code Online (Sandbox Code Playgroud)
有没有办法采用类级方法引用,FooBar::bar并获取实例方法引用?
即.如果我有
FooBar myFooBarInstance;
BiFunction<FooBar<A, B>, A, B> barFunction = FooBar::bar;
Run Code Online (Sandbox Code Playgroud)
是否有任何简单的方法来获得一个Function<A,B>与我定义的内容相匹配的实例
Function<A, B> myBarFunction = myFooBarInstance::bar;
Run Code Online (Sandbox Code Playgroud)
您想要做的是在函数编程领域中称为"部分函数应用程序",或者在功能较少的术语中将"将值绑定到参数".没有内置的方法,但是编写自己的方法很容易:
public static <T,U,R> Function<U,R> bind(BiFunction<T,U,R> f, T t) {
return u -> f.apply(t, u);
}
Run Code Online (Sandbox Code Playgroud)
然后你可以在你的情况下使用它:
FooBar<X,Y> instance=…;
BiFunction<FooBar<X,Y>,X,Y> barFunction=FooBar::bar;
Function<X,Y> myBarFunction=bind(barFunction, instance);
Run Code Online (Sandbox Code Playgroud)
要不就
// equivalent to myBarFunction=instance::bar
Function<X,Y> myBarFunction=bind(FooBar::bar, instance);
Run Code Online (Sandbox Code Playgroud)
需要注意的是实用的方法是紧张到您正在使用,即功能接口Function和BiFunction,而不是方法引用.它适用于任何BiFunction,无论是作为方法引用,lambda表达式还是普通类实现.但只有当你特别需要一个Function实例时才会有用,而不是一个带有一个参数的任意函数接口.您可以将a转换Function为另一个单参数函数类型,::apply但使用bind(bifunc, value)::apply不会x -> bifunc.apply(value, u)在需要实例的位置提供任何好处.
因此,如果您必须经常通过绑定第一个参数将BiFunctions 转换为Functions,则实用程序方法可能很有用.否则,只需在存在实际目标类型的上下文中使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
那么,如果你有像这样的功能
MyFunc4<U, W, X, Y, Z> func = …;
Run Code Online (Sandbox Code Playgroud)
你可以做点什么
MyFunc3<W, X, Y, Z> f3 = func.bind(u);
Run Code Online (Sandbox Code Playgroud)
要么
BiFunction<X, Y, Z> f2 = func.bind(u).bind(w);
Run Code Online (Sandbox Code Playgroud)