【发布时间】:2018-05-02 00:23:57
【问题描述】:
编译器给我这个错误“lambda表达式的目标类型必须是接口”:
Task<Iterable<Showing>> task = () -> sDAO.listFiltered();
listFiltered() 的返回类型是Iterable<Showing>。
如何将Task 接口与 lambda 一起使用?
【问题讨论】:
编译器给我这个错误“lambda表达式的目标类型必须是接口”:
Task<Iterable<Showing>> task = () -> sDAO.listFiltered();
listFiltered() 的返回类型是Iterable<Showing>。
如何将Task 接口与 lambda 一起使用?
【问题讨论】:
Task是抽象类,不是接口,所以不能直接用lambda表达式创建。
你通常只使用一个内部类来继承Task:
Task<Iterable<Showing>> task = new Task<Iterable<Showing>>() {
@Override
public Iterable<Showing> call throws Exception {
return sDAO.listFiltered();
}
});
如果您想要使用 lambda 表达式创建 Task 的功能,您可以创建一个可重用的实用程序方法来为您执行此操作。由于您需要在Task 中实现的抽象方法call 与Callable 中的接口方法具有相同的签名,因此您可以执行以下操作:
public class Tasks {
public static <T> Task<T> create(Callable<T> callable) {
return new Task<T>() {
@Override
public T call() throws Exception {
return callable.call();
}
};
}
}
由于Callable 是FunctionalInterface(即具有单个抽象方法的接口),因此可以使用 lambda 表达式创建它,因此您可以这样做
Task<Iterable<Showing>> task = Tasks.create(() -> sDAO.listFiltered());
在 OpenJDK 邮件列表中,有一个 explanation 说明为什么不允许使用 lambda 来创建(有效地)具有单个抽象方法的抽象类的子类。
【讨论】:
Task 或Callable 中的call 方法都不能是void。相反,声明它们返回 Void 并返回 null(Void 引用类型的唯一合法值)。