Когда я пытаюсь скомпилировать этот урезанный пример с помощью компилятора из JDK 9, 10 или 11:
public class UpperBounder {
public static void main(String[] args) {
print(Stream.of("a", "z", "b").collect(Collectors.toCollection(TreeSet::new)));
}
static void print(Set<?> set) {
System.out.println(set);
}
}
, я получаю эту ошибку:
ошибка:несовместимые типы: выведенный тип не соответствует верхней границе
print(Stream.of("a", "z", "b").collect(Collectors.toCollection(TreeSet::new)));
^
выведенный: INT # 1
верхняя граница: коллекция , набор, Object
, где INT # 1 - это тип пересечения:
INT # 1 расширяет Object, Set, Коллекция
Когда я пытаюсь скомпилировать его с JDK 1.8.0_121, я получаю другую ошибку.Но когда я или коллега пытаемся скомпилировать его с JDK 1.8.0_05, 1.8.0_20, 1.8.0_40 или 1.8.0_45, он компилируется нормально!
Замена TreeSet::new
на () -> new TreeSet<>()
делает эту компиляциюбез ошибок во всех версиях.
Я думаю, что эта программа четко звучит: аргумент print
будет TreeSet<String>
, что соответствует Set<?>
.Более того, сообщение об ошибке не имеет смысла для меня: тип пересечения Object
, Set<?>
и Collection<String>
должен соответствовать верхним границам Collection<String>
, Set<?>
и Object
!
Что происходит?Это ошибка?Или это как вывод типа должен работать?Почему это работало раньше?Как я могу заставить его работать снова (без использования лямбды вместо ссылки на метод)?