使用下限通配符时不兼容的类型

时间:2018-03-16 15:36:06

标签: java generics bounded-wildcard

我无法理解为什么我的代码有编译错误:

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的错误:

  

错误:(84,36)java:不兼容类型:不存在类型变量T的实例,以便java.util.function.Consumer<? super T>符合java.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中的一个错误?感谢。

3 个答案:

答案 0 :(得分:5)

Consumer<? super Something>不是Consumer<Integer>

编译器不知道Consumer类上没有生成器方法,因此它可以阻止您将其用作生产者。

就类型推断规则而言,例如ConsumerList之间没有区别。因此,停止编写以下内容的相同规则也会阻止您执行以下操作:

List<? super Integer> c = Arrays.asList("");
List<Integer> d = c;        // Compiler error; let's pretend it works.
Integer i = d.get(0);       // ClassCastException!

答案 1 :(得分:1)

您的修改答案:

我怀疑这是intellij中的一个错误。如果我删除变量声明,然后选择表达式并按 Ctrl + Alt + V 来提取变量,它会选择以下类型:

BiConsumer<? super Object, ? super Throwable> biConsumer = f2(throwable -> {});

尽管只是选择了自己,但它将lambda强调为错误。

答案 2 :(得分:0)

请尝试使用File-> Invalidate Caches并重新启动。