我想知道是否有办法将函数作为参数传递给方法。无论如何我在Java 8中可以做到这一点吗?请彻底解释我必须采取的步骤,并提前感谢您。
答案 0 :(得分:8)
是。查看java.util.function
包,了解可以使用的不同类型的功能接口。
您可能想要的是Function<T, R>
,它是一个函数的签名,它接受类型T
的单个参数并返回类型R
的值。对于更具体的案例,还有其他接口。例如,让我们说你想要某种谓词。然后,您可以使用Predicate<T>
来描述您希望接受一个方法,该方法根据对T
类型值的某种解释来返回布尔值。
这就是许多方法在流上工作的方式。例如,Stream<T>
中的forEach
是一个接受Consumer<? super T>
类型参数的方法。这基本上是一个函数,它接受一个参数并用它做一些事情。
就传递函数本身而言,您可以使用method references或通过lambdas创建功能接口的临时实现。
这是一个人为的例子,我在地图上迭代并将所有值添加到列表中:
List<Integer> list = new ArrayList<>();
Map<String, Integer> map = fromSomeMethod();
map.values().stream().forEach(list::add);
此处forEach
接受Consumer<? super T>
类型的消费者功能,在这种情况下是来自add
的{{1}}方法(Collection<E>
实现)。List<T>
因此,您基本上将一个方法作为参数传递给另一个方法。
这是我使用相同方法的另一个例子,但这次我打印出列表中的元素:
list.stream().forEach(System.out::println);
使用此方法,您可以创建接受其他方法的自己的方法,它就像定义java.util.function
中定义的任何一种类型的参数一样简单。对于您的错误回调案例,您可以执行以下操作:
public void doSomething(String something, Consumer<ErrorResult> errorHandler) {
//do some stuff
if(errorHappened) {
//call the error handler with a new ErrorResult object
errorHandler.accept(new ErrorResult(...));
}
}
然后让我们说你有一个方法只是在某个类中打印出错误结果
public class ConsoleErrorHandler {
public void handleError(ErrorResult result) {
System.out.println(result.getErrorMessage());
}
}
现在,您可以从doSomething
的实例引用handleError
来调用ConsoleErrorHandler
:
ConsoleErrorHandler handler = new ConsoleErrorHandler();
doSomething("Something", handler::handleError);
您甚至可以使用lambda:
临时执行此操作doSomething("Something", (ErrorResult result) -> {
System.out.println(result.getErrorMessage());
});
请注意,由于泛型,您需要进行编译时类型检查,这样您就不能简单地将接受单个参数的任何方法传递到doSomething
。
答案 1 :(得分:3)
Java中没有函数类型,因此您必须使用单个方法接口。
包java.util.function定义了很多,但是可以使用任何具有单个方法的接口。
例如:
// An interface with a single method that return
// something of type T
interface F<T> {
T doSomething();
}
class A {
// This method expect an instance of the interface F
private static String f( F<String> x ) {
// and then invokes its only method.
return x.doSomething();
}
// Test it
public static void main( String ... args ) {
//Call the method f using a
// this function literal: ()-> "hola"
System.out.println(
f( () -> "hola" )
);
}
}
函数文字:
() -> "hola"
隐含地满足界面F<T>
。
总之,您可以将类型指定为具有单个方法(任何接口)的接口。如果您使用java.util.function包中的一个现有接口,那就更好了。
我希望这会有所帮助。