是的。查看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> 类型的消费者函数,在本例中是来自Collection<E>(List<T> 实现)的add 方法。因此,您基本上已经将一个方法作为参数传递给另一个方法。
这是我使用相同方法的另一个示例,但这次我打印出列表的元素:
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,并从ConsoleErrorHandler 的实例引用handleError:
ConsoleErrorHandler handler = new ConsoleErrorHandler();
doSomething("Something", handler::handleError);
您甚至可以使用 lambda 临时执行此操作:
doSomething("Something", (ErrorResult result) -> {
System.out.println(result.getErrorMessage());
});
请注意,由于泛型,您会获得编译时类型检查,因此您不能简单地将接受单个参数的任何方法传递给doSomething。