Я не могу понять, почему у меня ошибка компиляции для этого кода:
private static <T> Consumer<T> f3()
{
return t -> {};
}
private static <T> Consumer<? super T> f4()
{
return t -> {};
}
@Test
public void test()
{
Consumer<Integer> action3 = f3();
Consumer<Integer> action4 = f4(); // ERROR
}
ошибка от javac 1.8.0_161:
Error:(84, 36) java: incompatible types: no instance(s) of type variable(s)
Texist so thatjava.util.function.Consumer<? super T>conforms tojava.util.function.Consumer<java.lang.Void>
Кто-нибудь может объяснить эту ошибку? Спасибо.
РЕДАКТИРОВАТЬ Я попытался упростить свой пример и сделал ошибку, сделав его слишком простым. Что меня интересует, так это объяснение этой ошибки, выводимой IntelliJ:
private static <T> BiConsumer<T, ? super Throwable> f1(Consumer<? super Throwable> consumer)
{
return null;
}
private static <T> BiConsumer<? super T, ? super Throwable> f2(Consumer<? super Throwable> consumer)
{
return null;
}
@Test
public void test()
{
BiConsumer<? super Integer, ? super Throwable> action1 = f1(throwable -> { });
BiConsumer<? super Integer, ? super Throwable> action2 = f2(throwable -> { }); // ERROR HERE
}
IntelliJ считает это ошибкой, потому что «переменная вывода T имеет несовместимые границы: ограничения равенства: нижние границы T: целое число». Но при компиляции все нормально, ошибок нет. Действительно ли это действительный Java-код и просто ошибка в IntelliJ? Спасибо.




Consumer<? super Something> - это не Consumer<Integer>.
Компилятор не знает, что в классе Consumer нет методов производителя, поэтому он не позволяет вам потенциально использовать его в качестве производителя.
Что касается правил вывода типов, например, нет разницы между Consumer и List. Таким образом, то же правило, которое запрещает вам писать следующее, также останавливает вас в том, что вы делаете:
List<? super Integer> c = Arrays.asList("");
List<Integer> d = c; // Compiler error; let's pretend it works.
Integer i = d.get(0); // ClassCastException!
Ответ на ваше редактирование:
Я подозреваю, что это ошибка в intellij. Если я удалю объявление переменной, а затем выберу выражение и нажму Ctrl + Alt + V, чтобы извлечь переменную, он выберет следующий тип:
BiConsumer<? super Object, ? super Throwable> biConsumer = f2(throwable -> {});
который, несмотря на то, что он только что выбрал сам себя, выделяет лямбду как ошибку.
Я тоже думаю, что это ошибка: если я изменю тип возвращаемого значения f2 с BiConsumer на Consumer, это сработает. Спасибо.
@FlorinM JetBrains действительно очень быстро исправляет ошибки!
Пожалуйста, попробуйте File-> Invalidate Caches и перезапустите.
@AndyTurner Я отредактировал, чтобы указать, где ошибка, извините за это.