После прочтения другого ответа (который является абсолютно правильным) и небольшого количества кофе, кажется, что объяснение в ошибке довольно логично.
Здесь есть два случая: явный лямбда-тип и неявный лямбда-тип. Явный тип:
Iterable<String> one = () -> Arrays.stream(arr).map(Object::toString).iterator();
Iterable<? extends CharSequence> iterable = one;
или как в примере с OP:
Iterable<? extends CharSequence> iterable2 = (Iterable<String>) () -> Arrays.stream(arr).map(Object::toString).iterator();
Мы прямо сообщаем компилятору, какой тип лямбда-выражения имеет вид: Iterable<String>
.
В этом случае компилятору нужно сделать только одно: посмотреть, можно ли назначить цель этому типу;довольно легко узнать и не очень связано с лямбдами как таковыми.
Другой тип - это неявный тип, когда компилятор должен вывести тип и все становится немного сложнее. «Хитрая» часть проистекает из того факта, что цель использует подстановочные знаки, поэтому может соответствовать более чем одному варианту. Там может быть бесконечное количество способов (конечно, конечно, но только чтобы доказать свою точку зрения), что лямбда может быть выведен как.
Может начаться что-то вроде этого, например:
Iterator<? extends Serializable> iter = Arrays.stream(arr).map(Object::toString).iterator();
Независимо от того, что будет сделано дальше, это не получится: CharSequence
не расширяется Serializable
, но String
делает;мы не сможем присвоить Iterable<? extends CharSequence> iterable
"независимо от типа-с-типом-с-сериализуемым-есть".
Или он может начинаться с:
Iterator<? extends Comparable<? extends CharSequence>> iter = Arrays.stream(arr).map(Object::toString).iterator();
Таким образом, теоретически компилятор может просто начать выводить, каким может быть этот тип, и проверять по одному, может ли "определенный" выводимый тип соответствоватьцель;но требует много работы, очевидно;таким образом, не сделано.
Другой способ намного проще: «порезать» цель и таким образом отбросить возможности вывода только до одного. Как только цель преобразуется в:
Iterable<CharSequence> iterable...
, работа, которую должен выполнить компилятор, становится намного более простой.
Это, кстати, не первый раз, когда я вижу эту неявную и явную логику типов в лямбдах.