Подтвердить что ты не робот

Может ли Java 8 реализовать интерфейс "на лету" для ссылки на метод?

Я изучаю новые возможности Java 8.

Я играю с разными примерами, и я нашел странное поведение:

public static void main(String[] args) {       
    method(Test::new);
}
static class Test{
}

private static void method(Supplier<Test> testSupplier){
    Test test = testSupplier.get();
}

Этот код успешно компилируется, но я не знаю, как это работает.

Почему Test::new приемлемо как поставщик?

Интерфейс поставщика выглядит очень просто:

@FunctionalInterface
public interface Supplier<T> {    
    T get();
}
4b9b3361

Ответ 1

Интерфейс Supplier имеет единственный (функциональный) метод, который:

  • не принимает никаких параметров;
  • возвращает объект.

Поэтому любой метод, соответствующий этим двум точкам, соответствует функциональному контракту Supplier (потому что методы будут иметь одну и ту же подпись).

Здесь рассматриваемый метод является ссылкой на метод. Он не принимает никаких параметров и возвращает новый экземпляр Test. Вы можете переписать его на:

method(() -> new Test());

Test::new в синтаксическом сахаре для этого лямбда-выражения.

Ответ 2

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

Прямой ответ на ваш вопрос заключается в том, что Supplier - это функциональный интерфейс, что означает, что он имеет один метод, отличный от метода по умолчанию. Конструктор для Test имеет ровно одну и ту же подпись (без аргументов, возвращает Test), и поэтому можно напрямую ссылаться на создание анонимного Supplier.

Есть четыре варианта ссылок на методы: ознакомьтесь с учебником, чтобы понять их все.

Ответ 3

Это может быть Function, а не поставщик, если требуется аргумент. Но ссылки на методы могут ссылаться на конструкторы таким же образом, как они относятся к методам; у них просто смешное имя (new).

Из учебника по Java, существует четыре типа ссылок на методы:

Kind                              Example
-------------------------------   ------------------------------------
Reference to a static method      ContainingClass::staticMethodName
Reference to an instance method   containingObject::instanceMethodName
of a particular object  
Reference to an instance method   ContainingType::methodName
of an arbitrary object of a 
particular type
Reference to a constructor        ClassName::new