Где реализован метод get () в интерфейсе поставщика? - PullRequest
1 голос
/ 23 апреля 2019

У меня есть этот кусок кода

public <T> someMethod(Supplier<T> supplier) {
        Objects.requireNonNull(supplier);
        SupplierThrowsException<T, Throwable> supplierThrowsException = supplier::get;
        return withThrowable(supplierThrowsException);
}

Я так называю

obj.someMethod(() -> myMethod(message))

Я на 100% уверен, что класс объекта, возвращаемого myMethod(), не реализует интерфейс поставщика. Так где же реализация get().

Я прошел Javadoc, я ничего не получил. Я хотел бы понять, что здесь происходит.

Я нашел это и это но это не проясняет мои сомнения. Дайте мне знать, если я что-то здесь упускаю.

Ответы [ 4 ]

3 голосов
/ 23 апреля 2019

В этом вызове:

obj.someMethod(() -> myMethod(message))

вы реализуете интерфейс Supplier, используя лямбда-выражение - () -> myMethod(message).

Это как будто (я говорю «как будто»)потому что это не то, что на самом деле происходит под капотом. Здесь это то, что происходит под капотом) вы создали внутренний класс, реализующий Supplier, подобный этому:

static class MyInnerClass implements Supplier<SomeClass> {
    public SomeClass get() {
        return myMethod(message);
    }
}

И затем переданныйnew MyInnerClass() до someMethod.

3 голосов
/ 23 апреля 2019

Я на 100% уверен, что класс объекта, возвращаемого myMethod(), не реализует интерфейс Supplier.

Конечно, но выражение () -> myMethod(message) делает.

Пожалуйста, прочитайте 15.27.4.Оценка времени выполнения лямбда-выражений .

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

Либо выделяется и инициализируется новый экземпляр класса со свойствами, указанными ниже, либо существующий экземпляр класса со свойствами, указанными ниже.ссылка .

Значение лямбда-выражения является ссылкой на экземпляр класса со следующими свойствами:

  • Класс реализует целевой функционалтип интерфейса и, если целевой тип является типом пересечения, любой другой тип интерфейса, упомянутый в пересечении.

Короче говоря, лямбда-выражение () -> myMethod(message) будет преобразовано вэкземпляр Supplier.

Где реализация get ()?

Вы предоставили его в теле лямбды.

() -> myMethod(message) 

(это выражение оператора, более короткая форма для создания лямбда-тела)

() -> {
    return myMethod();
}

(это блок, совместимый со значением, более расширенная версия, в которой может быть объявлено много операторов)

0 голосов
/ 23 апреля 2019

Supplier является функциональным интерфейсом и содержит следующий единственный абстрактный метод:

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

Теперь вы предоставили метод definition из get вместе с instantiation со следующим вызовом:

obj.someMethod(() -> myMethod(message))

Над строкой переводится следующим образом:

obj.someMethod(new Supplier() {

@Override
public T get() 
{ 
  return myMethod(message);
}

});
0 голосов
/ 23 апреля 2019

Я думаю, что этот документ может пролить свет на ваш вопрос: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#target-typing

Чтобы определить тип лямбда-выражения, компилятор Java использует целевой тип контекста или ситуации, в которой было найдено лямбда-выражение. Из этого следует, что вы можете использовать лямбда-выражения только в ситуациях, когда компилятор Java может определить целевой тип:

Объявления переменных

1009 * Назначение *

Заявления о возврате

Инициализаторы массивов

Аргументы метода или конструктора

Тела лямбда-выражения

Условные выражения,?:

Составные выражения

...