刚刚发现了一种奇怪而有趣的Lambda行为。
让我们拥有以下课程:
private class Task implements Runnable {
@Override
public void run() {
// something to process
}
}
以下语句正在编译并运行:
Callable task = Task::new;
有人可以解释为什么这是可能的吗?
修改:
根据以下答案,请查看以下声明:
1
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(Task::new);
2
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new Task());
这里发生的正是上述情况。
原因是ExecutorService
有两种方法:
submit(Runnable);
submit(Callable);
因此,使用来自1的代码。执行者将在其内部线程上处理以下内容:
new Task()
来自2.的版本实际上将调用submit(Runnable)
方法,并且将执行Task.run
中的代码。
结论:小心使用Lambdas :)
答案 0 :(得分:4)
Callable 不使用Runnable
实例进行初始化,它使用对生成 a的Task
构造函数的方法引用进行初始化执行时Runnable
。
换句话说,如果执行Callable
,它将返回一个新的Task
对象,其中尚未尚未运行。 Task
实现Runnable
实际上与此完全无关。
如果您不使用原始类型,这将更加清晰。可以将Task::new
分配给Callable<Task>
,因为它不需要参数并返回任务。
答案 1 :(得分:2)
要实现Callable<V>
接口,必须使用签名V call()
实现一个方法。
因此,您可以使用任何不带任何方法的方法引用来实现此接口,并返回一些引用类型,其中包括构造函数方法引用,例如Task::new
。
实际上,任何具有无参数构造函数的类都可以这样使用:
Callable<SomeClass> callable = SomeClass::new;