方法参考的组成
这与这个问题有关: 如何进行function组合?
我注意到方法引用可以分配给声明为Function
的变量,因此我假设它应该具有andThen
或compose
函数,因此我希望我们可以直接组合它们。 但显然我们需要将它们分配给一个声明为Function
first的变量(或者在调用之前进行类型转换),然后才能调用andThen
或者在它们上进行compose
。
我怀疑我可能会对这应该如何运作有一些误解。
所以我的问题:
- 在我们调用
andThen
方法之前,为什么我们需要首先进行类型转换或将其分配给变量? - 以这种方式需要完成的方法引用的类型究竟是什么?
示例代码如下。
public class MyMethods{ public static Integer triple(Integer a){return 3*a;} public static Integer quadruple(Integer a){return 4*a;} public int operate(int num, Function f){ return f.apply(num); } public static void main(String[] args){ MyMethods methods = new MyMethods(); int three = methods.operate(1, MyMethods::triple); // This is fine // Error below // int twelve = methods.operate(1, (MyMethods::triple).andThen(MyMethods::quadruple)); // But this one is fine Function triple = MyMethods::triple; Function quadruple = MyMethods::quadruple; int twelve = methods.operate(1, triple.andThen(quadruple)); // This one is also fine int twelve2 = methods.operate(1, ((Function)MyMethods::triple).andThen(MyMethods::quadruple)); } }
有关错误的更多说明
在Eclipse中,它突出显示错误消息:
此表达式的目标类型必须是function接口
在Java 8编译器中,错误是:
java8test.java:14:错误:这里不期望方法引用 int 12 = methods.operate(1,(MyMethods :: triple).andThen(MyMethods :: quadruple)); ^ 1错误
(实际上,为什么Eclipse中的错误与Java 8编译器中的错误不同?)
正如Brian Goetz(Java lambdas的项目负责人)所说, “Lambda表达式没有内在类型” (也适用于方法引用)。 这就是为什么在方法可用之前需要强制转换(或赋值) Function
。
Eclipse显示来自JDK编译器(javac)的不同错误消息的原因是Eclipse使用自己的Java编译器,称为ecj,这是一个与javac完全不同的程序。 这就是BTW为什么Eclipse可以在JRE上运行而不需要完整的JDK安装。
如果创建static
辅助方法(其中所有函数都是参数而不是方法调用接收器),则可以在没有类型转换或临时变量的情况下离开:
static Function chain( Function super V, ? extends T> f1, Function super T, R> f2) { return f2.compose(f1); }
然后你可以简单地说:
int twelve = methods.operate(1, chain(MyMethods::triple, MyMethods::quadruple));
但是,请记住,与简单的lambda表达式相比,链接方法引用这种方式在源代码中既不短,也不在运行时更高效:
int twelve = methods.operate(1, i -> quadruple(triple(i)));
注意最后一个解决方案如何不需要类型转换,附加变量和辅助方法。 如果你已经存在一个适合需要函数的方法,那么方法引用是一个很好的工具,但是用多个方法引用组合一个函数并不是很有用(在大多数情况下)。