Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda: Callable variable initiated with a Runnable instance

Just found a strange and interesting Lambda behavior.

Let's have the following class:

private class Task implements Runnable {
    @Override
    public void run() {
       // something to process
    }
}

The following statement is compiling and running:

Callable task = Task::new;

Could somebody explain why this is possible ?

EDIT:

Based on answers below, check the following statements:

1.

ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(Task::new);

2.

ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(new Task());

On the first glance, seems the same, but actually does a totally different thing.

What happens here is exactly the above situation.

The reason is that ExecutorService has two methods:

submit(Runnable); submit(Callable);

So, using the code from 1. the executor will process the following on it's internal thread:

new Task()

The version from 2. will actually call the submit(Runnable) method and the code from Task.run will be executed.

Conclusion: just be careful with Lambdas :)

like image 450
Gyuri Majercsik Avatar asked Sep 17 '26 08:09

Gyuri Majercsik


2 Answers

The Callable is not initialized with a Runnable instance, it is initialized with a method reference to the Task constructor that will produce a Runnable when executed.

In other words, if you execute that Callable, it will return a new Task object that has not yet been run. That Task implements Runnable is actually completely irrelevant here.

This would be clearer if you didn't use the raw type. Task::new can be assigned to Callable<Task> because it is something that takes no parameters and returns a Task.

like image 174
Michael Borgwardt Avatar answered Sep 19 '26 20:09

Michael Borgwardt


To implement the Callable<V> interface one must implement a method with the signature V call().

Therefore, you can implement this interface with method references of any methods that take nothing and return some reference type, which includes constructor method references such as Task::new.

In fact, any class having a parameter-less constructor can be used this way:

Callable<SomeClass> callable = SomeClass::new;
like image 27
Eran Avatar answered Sep 19 '26 20:09

Eran



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!