Как компилятор узнает, какой класс реализует lamba? - PullRequest
0 голосов
/ 18 октября 2019

Я вижу, Thread() принимает Runnable и String для конструкторов с одним аргументом. Как компилятор узнает, что лямбда-класс реализует класс Runnable, а не класс String?

    (new Thread( () -> {
        System.out.println("Deleting stats...");
    })).start();

Может быть, это зависит от количества методов в классе / интерфейсе? Но что если в классе есть несколько конструкторов, которые принимают класс с одним аргументом, который имеет только один метод, например:

Thread( Runnable r );
Thread( Comparable c );
Thread( ActionListener al );

Что происходит тогда, когда вы пытаетесь реализовать лямбду? Как бы компилятор узнал, какой класс реализует лямбда?

Ответы [ 2 ]

2 голосов
/ 18 октября 2019

Компилятор Java должен выбрать тип функционального интерфейса для типа лямбда-выражения. Это регулируется JLS, раздел 15.27.3 , в котором говорится:

Лямбда-выражение совместимо в контексте назначения, контексте вызова или контексте приведения с целевым типомT, если T - это тип функционального интерфейса (§9.8) и выражение соответствует с типом функции тип наземной цели , полученной из T.

Тип String не является функциональным типом интерфейса, но Runnable является. Лямбда не принимает аргументов и не возвращает данных, поэтому она соответствует с Runnable.

В более общем случае типы параметров в лямбда-выражении должны соответствовать типам параметроводин абстрактный метод функционального типа интерфейса, и возвращаемые типы также должны совпадать.

В вашем примере каждый из 3-х типов функционального интерфейса отличается, так что самое большее один будет соответствовать. Если существует несколько типов функциональных интерфейсов, которые могли бы совпадать, это было бы неоднозначно, разрешимо только путем приведения лямбда-выражения к предполагаемому типу функционального интерфейса.

1 голос
/ 18 октября 2019

Лямбда-выражения преобразуются в экземпляр класса, реализующего функциональный интерфейс. «Функциональный интерфейс» означает интерфейс только с 1 (не по умолчанию) методом.

Строка не является интерфейсом - это класс. Таким образом, компилятор смотрит на лямбда-выражение и знает, что если код имеет смысл, он должен преобразовать лямбда в экземпляр реализации Runnable, так как это единственно возможная вещь, которая может работать!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...