I am having a java compiler error that I don't understand. It seems that Consumer< ? > and Consumer< T > (with T extends Object) are not equivalent in method signature arguments. Please check out the code below:
import java.util.function.Consumer;
public class MyClass {
public void joker(Consumer<?> fct) {}
public <T> void generic(Consumer<T> fct) {}
public void myConsumer(String s) {}
public void doesNotCompile()
{
joker(this::myConsumer); // COMPILE ERROR : (In Eclipse : ) The type MyClass does not define myConsumer(Object) that is applicable here
generic(this::myConsumer); // Works fine : how come are "T" and "?" not equivalent here ?
// The following also works fine as usual :
Consumer<String> cs = this::myConsumer;
joker(cs);
joker((String s) -> myConsumer(s));
}
}
The error is a bit different when I compile the code via command-line rather than in Eclipse:
D:\>javac -Xdiags:verbose MyClass.java
MyClass.java:11: error: method joker in class MyClass cannot be applied to given types;
joker(this::myConsumer);
^
required: Consumer<?>
found: this::myConsumer
reason: argument mismatch; invalid method reference
method myConsumer in class MyClass cannot be applied to given types
required: String
found: Object
reason: argument mismatch; Object cannot be converted to String
1 error
It is slightly clearer but I still don't get the point. Note you get an analog error with java.util.function.Function but not with java.util.function.Supplier. I therefore believe the error occurs for any functional interface taking in a parameter.
Is this a compiler bug or am I missing something here? In case of the latter (most likely), can someone tell the reason of such a behavior design?
I feel that there is something going wrong with type inference. I also barely know that JVM handles lambdas and method reference differently (AFAIK via MethodHandler). But to be honest, I am just confused.
Help? ¯\ (ツ)/¯