Как оператор ссылки на метод принимается там, где ожидается Runnable Instance? - PullRequest
0 голосов
/ 15 февраля 2019

Недавно я наткнулся на пример кода, где оператор ссылки на метод используется для ссылки на вызов метода.Есть 2 вопроса, на которые я ищу ответ 1. Метод execute, где он вызывается, ожидает класс Runnable.Этот код компилирует файл и не дает ошибок, почему (класс приложения не Runnable)?2. если я заменю executorService.execute (app :: someMethod);с executorService.execute (app.someMethod ());это дает ошибку компиляции почему?

public class Temp {

private static final Logger LOGGER = LoggerFactory.getLogger(Temp.class);

/**
 * @param args the command line arguments - not used
 */`enter code here`
public static void main(String... args) {
    final App app = new App();
    ExecutorService executorService = Executors.newFixedThreadPool(3);
    for (int i = 0; i < 3; i++) {
        executorService.execute(app::someMethod);
    }
    executorService.shutdown();
    try {
        executorService.awaitTermination(10, TimeUnit.SECONDS);
    } catch (InterruptedException ie) {
        LOGGER.error("ERROR: Waiting on executor service shutdown!");
    }
}

}
class App {
     public void someMethod() {
           // Some logic
     }
}

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

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значения, возвращаемые методами, могут быть отброшены, и ссылки на методы (а также лямбда-выражения) соблюдают это поведение.

0 голосов
/ 15 февраля 2019

1) Да, класс App не является Runnable, но в вашем примере это не объект App, который вы передаете для выполнения метода, а вместо этого вы делаете ссылку на метод там.

2) app ::someMethod - это ссылка на метод экземпляра определенного объекта.app.someMethod () - это просто вызов someMethod (), и ожидается, что он возвращает объект, реализующий интерфейс Runnable.Это не так, поэтому вы получаете сообщение об ошибке.

...