Почему эта ссылка на метод Java 8 не работает для System.out.println (LocalDate :: now) ;? - PullRequest
5 голосов
/ 25 мая 2019

Возможно, я не полностью понимаю концепцию функциональных интерфейсов Java 8 и / или ссылок на методы. Я просто не понимаю, почему следующий код имеет «Целевой тип этого выражения должен быть функциональным интерфейсом»:

import java.time.LocalDate;

interface Today{
    LocalDate getTodayDate(); 
}

Класс для тестирования:

class Test{
    public static void main(String[] args) {

        Today today = () -> LocalDate.now();
        System.out.println(today::getTodayDate);//Problem with this one                 
    }   
}

Ответы [ 2 ]

3 голосов
/ 25 мая 2019

Вы используете ссылку на ваш метод в контексте, где его целевой тип неизвестен.

Это сработало бы, если бы java.io.PrintStream имел метод, подобный следующему:

public void println(Today dateSupplier){
    print(dateSupplier.getTodayDate());
}

Но это не сигнатура println.

Нет причин делать это, но способ заставить ваш код работать, это вызвать собственный метод интерфейса, но это не может быть оправдано ...

System.out.println(today.getTodayDate()); //calls println(Object)

Если в этот контракт не входит более одного класса / типа, вам может потребоваться изменить код.

2 голосов
/ 25 мая 2019

В описании вашего вопроса вы говорите, что полученная ошибка: «Тип цели этого выражения должен быть функциональным интерфейсом»;но строка, где вы показываете, что:

System.out.println(today::getTodayDate);//Problem with this one

будет отображать другое сообщение об ошибке.Поэтому я думаю, что требуется более широкое объяснение.

Кажется, вам сначала нужно создать @FunctionInterface с именем Today, чтобы этот код работал, что-то вроде:

@FunctionalInterface
interface Today {
    LocalDate getTodayDate();
}

Когда этосоздается, это тоже будет работать:

Today today = () -> LocalDate.now(); 

, что будет эквивалентно:

Today today = LocalDate::now;

Нет реальной необходимости создавать Today, так как java.util.Supplier<T> существует и выполняетто же самое - ничего не принимает в качестве входных данных и возвращает T;но если вы хотите поиграть - вы могли бы.

На самом деле тот факт, что вы ввели этот интерфейс Today, сделает объяснение немного проще.

Компилятор видит: today::getTodayDate(в строке System.out.println(today::getTodayDate);) и должен «понять», что это такое;это может быть по крайней мере две вещи: Today или java.util.Supplier - это не может сказать наверняка;именно поэтому говорят, что лямбда-выражения и ссылки на методы являются поли-выражениями - их тип выводится в контексте использования (как и дженерики).Поскольку компилятор не может определить, что это на самом деле, он завершается неудачей.

Вы можете сделать явное приведение к типу для этой компиляции:

System.out.println((Today) today::getTodayDate);

или:

System.out.println((Supplier<LocalDate>) today::getTodayDate);

Но проблема в том, что даже если это компилируется, работает и печатает «что-то» - то, что он действительно печатает, не указано в JLS и зависит от реализации.

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