История вопроса: недавно я написал ответ, где я предложил написать следующий код:
Files.write(Paths.get("PostgradStudent.csv"),
Arrays.stream(PGstudentArray).map(Object::toString).collect(Collectors.toList()),
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
Поразмыслив, я сказал: «На самом деле мне здесь не нужен список, мне просто нужен Iterable<? extends CharSequence>
».
Поскольку у Stream<T>
есть метод Iterator<T> iterator()
, я подумал, ну, это просто:
Iterable<? extends CharSequence> iterable = () -> Arrays.stream(arr).map(Object::toString).iterator();
(Я извлек его в локальную переменную для этого вопроса, я хотел бы сделать это встроенным в конце.)
К сожалению, это не компилируется без дополнительных подсказок типа:
error: incompatible types: bad return type in lambda expression
Iterable<? extends CharSequence> iterable = () -> Arrays.stream(arr).map(Object::toString).iterator();
^
Iterator<String> cannot be converted to Iterator<CharSequence>
Конечно, добавление подсказок типа сделает эту работу:
Iterable<? extends CharSequence> iterable2 = (Iterable<String>) () -> Arrays.stream(arr).map(Object::toString).iterator();
Iterable<? extends CharSequence> iterable3 = () -> Arrays.stream(arr).<CharSequence>map(Object::toString).iterator();
В моем понимании компилятор Java выполняет следующие функции:
- Он смотрит на целевой тип выражения, которым является
Iterable<? extends CharSequence>
. - Затем он определяет тип функции этого интерфейса, в моем случае это
() -> Iterator<? extends CharSequence>
. - Затем он смотрит на лямбду и проверяет, совместима ли она.
В моем случае лямбда имеет тип() -> Iterator<String>
.
Что совместимо с типом функции, определенным на шаге 2.
Интересно, что если я изменю цель лямбды на Supplier
:
Supplier<Iterator<? extends CharSequence>> supplier = () -> Arrays.stream(arr)
.map(Object::toString)
.iterator();
он будет компилироваться нормально.
Теперь возникает вопрос: почему javac не может определить правильный тип для этой лямбды?
Iterable<? extends String>
Не? extends CharSequence
- person Ravindra Ranwala   schedule 24.10.2019String
является окончательным, он будет равенIterable<String>
. - person Johannes Kuhn   schedule 24.10.2019Files.write
. Присваивание - это простой способ указать цель лямбда. - person Johannes Kuhn   schedule 24.10.2019