Java – invalid method reference for overloaded methods with different arities
Try compiling the expression comparator When comparing (string:: tolower case), the java compiler returns an error For more information, see the following questions:
Why Comparator. comparing doesn’t work with String::toLowerCase method reference?
I tried to minimize the problem In particular, I have removed almost all dependencies to other classes The main method contains two method calls The first statement compiles without errors, while the second statement generates errors
interface Fun<T,R> { R apply(T t); } public final class Foo { public static void main(String... args) { invoke(Foo::bar); // OK invoke(Foo::baz); // ERROR } private static <T,U> void invoke(Fun<T,U> f) { } private String bar() { return null; } private String baz() { return null; } private String baz(Integer i,Integer j) { return null; } }
This is strange because the second Baz method should not be suitable for this situation because the number of parameters does not match I've seen jls8 (15.13) However, it doesn't help because the rules of method reference are very complex
Q: why do compile errors occur in the second case? Will compilation errors really occur according to JLS? According to some comments on another issue, there are no compilation errors in NetBeans
For reference, I use JDK 8 version 1.8 0-b132. If you compile the program on the command line, the compiler displays the following error message:
$/opt/jdk8/bin/javac Foo.java Foo.java:6: error: incompatible types: cannot infer type-variable(s) T,U invoke(Foo::baz); // ERROR ^ (argument mismatch; invalid method reference no suitable method found for baz(Object) method Foo.baz() is not applicable (actual and formal argument lists differ in length) method Foo.baz(Integer,Integer) is not applicable (actual and formal argument lists differ in length)) where T,U are type-variables: T extends Object declared in method <T,U>invoke(Fun<T,U>) U extends Object declared in method <T,U>) Foo.java:6: error: invalid method reference invoke(Foo::baz); // ERROR ^ non-static method baz() cannot be referenced from a static context 2 errors
Solution
Jls8 (15.13) is confusing, but it does show examples similar to yours, which shows that their ambiguity in search can not be solved
For your example, IntelliJ says invoke (foo:: Baz); It's a circular inference. I think it's more related to the inference type of the call and the combination of foo:: Baz
This can be solved by typing the calling function, similar to JSL (example 15.13.1)
Foo < foo, string > Call (foo:: Buzz); – Equivalent to, I want to use Foo's void method to return a string aka string baz()
interface Fun<T,R> { R apply(T t); } interface Fun2<T,U,R> { R apply(T t,U u); } public final class Foo { public static void main(String... args) { invoke(Foo::bar); // OK Foo.<Foo,String>invoke(Foo::baz); // NO ERROR Fun2<Foo,Integer,String> f2 = Foo::baz; // Overloaded method baz } private static <T,U> f) { } private String bar() { return null; } private String baz() { return null; } private String baz(Integer i) { return null; } }
I agree with you that Baz (integer I) is not a valid parameter. You can set it to static or instance from foo without calling it I think if the method overloads and it tries to infer the type, the search algorithm will exit Because it uses only one method signature