ExecutorService.execute
ожидает аргумент типа Runnable
.
Чтобы ответить на ваш последний вопрос первым ... App.someMethod()
- это метод void
(т.е. он ничего не возвращает).Так как тип возвращаемого значения app.someMethod()
равен void
, а тип void
нельзя присвоить переменной или аргументу метода типа Runnable
, вы получаете ошибку компиляции.
Теперь,Что касается вашего первого вопроса ... Runnable
интерфейс - это функциональный интерфейс , потому что он объявляет один абстрактный метод (SAM):
@FunctionalInterface
public interface Runnable {
void run();
}
SAM здесь - void run()
, который не получает никаких аргументов и является void
методом.
Теперь ссылка на метод app::someMethod
равна нацеливанием void someMethod()
метода класса App
,чья подпись соответствует , что один из run
метода интерфейса Runnable
(под match я имею в виду, что тип возвращаемого значения обоих методов равен void
, и что ни один из нихполучает любой аргумент).
Итак, когда вы передаете ссылку на метод app::someMethod
в качестве аргумента методу executorService.execute
, компилятор безопасно преобразует в экземпляр Runnable
.
РЕДАКТИРОВАТЬ: Как отмечает пользователь @MC Emperor в комментариях, someMethod
метод App
класса может вернуть что-то (т.е. это не обязательно должен быть void
метод).В этом случае, как указано в спецификации (см. JLS § 15.27.3 , спасибо за ссылку!), Возвращаемое значение будет просто отброшено.
Это потому, что в Javaзначения, возвращаемые методами, могут быть отброшены, и ссылки на методы (а также лямбда-выражения) соблюдают это поведение.