jus*_*alf 16 java eclipse function-composition java-8 method-reference
这与这个问题有关:如何进行功能组合?
我注意到方法引用可以分配给声明为的变量Function,因此我假设它应该具有andThen或compose函数,因此我希望我们可以直接组合它们.但很显然,我们需要把它们分配给声明为可变的Function第一(或类型转换调用之前)之前,我们可以称之为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<Integer, Integer> 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<Integer, Integer> triple = MyMethods::triple;
Function<Integer, Integer> quadruple = MyMethods::quadruple;
int twelve = methods.operate(1, triple.andThen(quadruple));
// This one is also fine
int twelve2 = methods.operate(1, ((Function<Integer, Integer>)MyMethods::triple).andThen(MyMethods::quadruple));
}
}
Run Code Online (Sandbox Code Playgroud)
在Eclipse中,它突出显示错误消息:
此表达式的目标类型必须是功能接口

在Java 8编译器中,错误是:
java8test.java:14: error: method reference not expected here
int twelve = methods.operate(1, (MyMethods::triple).andThen(MyMethods::quadruple));
^
1 error
(实际上,为什么Eclipse中的错误与Java 8编译器中的错误不同?)
Chr*_*ung 14
正如Brian Goetz(Java lambdas的项目负责人)所说,"Lambda表达式没有内在类型"(也适用于方法引用).这就是为什么Function在方法可用之前需要转换(或赋值)类型的原因.
Eclipse显示来自JDK编译器(javac)的不同错误消息的原因是Eclipse使用自己的Java编译器,称为ecj,这是一个与javac完全不同的程序.这就是BTW为什么Eclipse可以在JRE上运行而不需要完整的JDK安装.
如果创建一个static辅助方法(其中所有函数都是参数而不是方法调用接收器),则可以在没有类型转换或临时变量的情况下离开:
static <T,V,R> Function<V, R> chain(
Function<? super V, ? extends T> f1, Function<? super T, R> f2) {
return f2.compose(f1);
}
Run Code Online (Sandbox Code Playgroud)
然后你可以简单地说:
int twelve = methods.operate(1, chain(MyMethods::triple, MyMethods::quadruple));
Run Code Online (Sandbox Code Playgroud)
但是,请记住,与简单的lambda表达式相比,链接方法引用这种方式在源代码中既不短,也不在运行时更高效:
int twelve = methods.operate(1, i -> quadruple(triple(i)));
Run Code Online (Sandbox Code Playgroud)
注意最后一个解决方案如何不需要类型转换,附加变量和辅助方法.如果您已经存在一个适合需要函数的方法,但是从多个方法引用中组合函数并不是很有用(在大多数情况下),方法引用是一个很好的工具.