Lambda: callable variable triggered by Runnable instance
Just found the strange and interesting behavior of the Lambda.
Let's have the following class:
private class Task implements Runnable {
@Override
public void run() {
// something to process
}
}
The following statement will compile and run:
Callable task = Task::new;
Can anyone explain why this is possible?
EDIT
Based on the answers below, check the following statements:
1.
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(Task::new);
2.
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new Task());
At first glance it seems the same, but in fact it does a completely different thing.
What is happening here is exactly the above situation.
The reason is that it ExecutorService
has two methods:
submit(Runnable);
submit(Callable);
So, using the code from 1., the executor will process the internal stream on it:
new Task()
The version from 2. will actually call the method submit(Runnable)
and the code from Task.run
.
Conclusion: be careful with Lambdas :)
source to share
The callable is not instantiated Runnable
, it is initialized by a method reference to the constructor Task
that will be issued Runnable
on execution.
In other words, if you do this Callable
, it will return a new object Task
that hasn't been started yet. What Task
implements Runnable
is really completely irrelevant.
It would be clearer if you weren't using a raw type. Task::new
can be assigned Callable<Task>
because it is something that takes no parameters and returns a task.
source to share
To implement the interface, Callable<V>
you must implement a method with a signature V call()
.
Hence, you can implement this interface with method references of any methods that accept nothing and return some reference type that includes constructor method references such as Task::new
.
In fact, any class that has a parameterless constructor can be used like this:
Callable<SomeClass> callable = SomeClass::new;
source to share