Reputation: 189
I can't understand why I have a compilation error for this code:
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
}
the error from javac 1.8.0_161:
Error:(84, 36) java: incompatible types: no instance(s) of type variable(s)
T
exist so thatjava.util.function.Consumer<? super T>
conforms tojava.util.function.Consumer<java.lang.Void>
Can anyone explain this error? Thanks.
EDIT I tried to simplify my example, and I did an error by making it too simple. What I'm interested is an explanation for this error which is output by 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 considers this an error because "inference variable T has incompatible bounds: equality constraints: T lower bounds: Integer". But when compiling it, it's fine, no error. Is this an actually valid Java code and just a bug in IntelliJ? Thanks.
Upvotes: 2
Views: 1024
Reputation: 140328
An answer for your edit:
I suspect this is a bug in intellij. If I remove the variable declaration, and then select the expression and press Ctrl+Alt+V to extract a variable, it picks the following type:
BiConsumer<? super Object, ? super Throwable> biConsumer = f2(throwable -> {});
which, despite just having picked itself, it highlights the lambda as an error.
Upvotes: 1
Reputation: 140328
A Consumer<? super Something>
isn't a Consumer<Integer>
.
The compiler doesn't know that there are no producer methods on the Consumer
class, so it stops you potentially using it as a producer.
As far as the type inference rules are concerned, there is no difference between Consumer
and List
, for example. So the same rule which stops you writing the following also stops you in what you are doing:
List<? super Integer> c = Arrays.asList("");
List<Integer> d = c; // Compiler error; let's pretend it works.
Integer i = d.get(0); // ClassCastException!
Upvotes: 5