sto*_*r96 5 java generics lambda functional-interface method-reference
我有一个功能界面
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
@FunctionalInterface
public interface SubmitterCompletable extends Submitter {
@Override
<T> CompletableFuture<T> submit(Callable<T> task);
}
Run Code Online (Sandbox Code Playgroud)
和两个函数
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
public final class CompletableFutureUtils {
public static <U> CompletableFuture<U> runAsync(Callable<U> callable) {
// ...
}
public static <U> CompletableFuture<U> runAsync(Callable<U> callable, Executor executor) {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
我想SubmitterCompletable使用 lambda 表达式或方法引用从这些函数创建 s。第一个通过使用方法引用工作得很好。
SubmitterCompletable submitterCompletable = CompletableFutureUtils::runAsync;
Run Code Online (Sandbox Code Playgroud)
然而,对于第二个,我必须使用 lambda 表达式来传递 an Executor,但它不起作用。
Executor executor = /* ... */;
SubmitterCompletable submitterCompletable = c -> CompletableFutureUtils.runAsync(c, executor);
// Illegal lambda expression: Method submit of type SubmitterCompletable is generic
Run Code Online (Sandbox Code Playgroud)
我的问题是这种情况下是否有有效的 lambda 表达式,或者在这种情况下我是否必须创建一个匿名类?
这里的问题是“只有当函数接口中的方法没有类型参数时,lambda 表达式才可以用于函数接口”。(JLS11,15.27.3 Lambda 表达式的类型),但有一个例外 -全等方法引用并非如此。
这就是为什么它在第一个示例中有效而在第二个示例中无效的原因:
SubmitterCompletable submitterCompletable = CompletableFutureUtils::runAsync; (OK)
SubmitterCompletable submitterCompletable = c -> <anything> (NOT OK)
Run Code Online (Sandbox Code Playgroud)
我能想到的实现你想要的东西的选择并不多:
实现接口(如您所提到的就地使用匿名类或作为独立类)。
在您的内部使用一个中间帮助程序类,CompletableFutureUtils该类将保留对执行程序的引用,并公开与您的提交者的功能方法一致的方法,该方法会将调用委托给底层runAsync(Callable<U> callable, Executor executor)util 的方法。
示例代码:
public final static class CompletableFutureUtils {
public static <U> CompletableFuture<U> runAsync(Callable<U> callable) {
...
}
public static <U> CompletableFuture<U> runAsync(Callable<U> callable, Executor executor) {
...
}
public static ExecutorRunnerProxy using(Executor executor) {
return new ExecutorRunnerProxy(executor);
}
public static final class ExecutorRunnerProxy {
private final Executor executor;
private ExecutorRunnerProxy(Executor executor) {
this.executor = executor;
}
public <T> CompletableFuture<T> runAsync(Callable<T> task) {
return CompletableFutureUtils.runAsync(task, executor);
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
SubmitterCompletable submitterCompletable = CompletableFutureUtils::runAsync;
SubmitterCompletable submitterWithExecutor = CompletableFutureUtils.using(executor)::runAsync;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
619 次 |
| 最近记录: |