问题
I got this little code to test out Callable
. However, I find it pretty confusing how the Compiler could know if the Lambda is for the Interface Callable or Runnable since both don't have any parameter in their function.
IntelliJ, however, shows that the Lambda employs the code for a Callable.
public class App {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(() ->{
System.out.println("Starting");
int n = new Random().nextInt(4000);
try {
Thread.sleep(n);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("Finished");
}
return n;
});
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.MINUTES );
}
}
回答1:
See the documentation of ExecutorService which has 2 submit
methods with one parameter:
- submit(Callable<T> task) using Callable<T> which has method call() returning
T
. - submit(Runnable task) usnig Runnable which has method run() returning nothing (
void
).
Your lambda gives an output, returns something:
executorService.submit(() -> {
System.out.println("Starting");
int n = new Random().nextInt(4000);
// try-catch-finally omitted
return n; // <-- HERE IT RETURNS N
});
So the lambda must be Callable<Integer>
which is a shortcut for:
executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("Starting");
int n = new Random().nextInt(4000);
// try-catch-finally omitted
return n;
}}
);
To compare, try the same with Runnable
and you see it's method's return type is void
.
executorService.submit(new Runnable() {
@Override
public void run() {
// ...
}}
);
回答2:
The main difference in the signature is that a Callable
returns a value while a Runnable
does not. So this example in your code is a Callable
, but definately not a Runnable
, since it returns a value.
来源:https://stackoverflow.com/questions/51848591/how-does-java-differentiate-callable-and-runnable-in-a-lambda