具有不同arities的重载方法的方法引用无效

尝试编译表达式Comparator.comparing(String::toLowerCase) ,Java编译器返回错误。 有关更多信息,请参阅以下问题:

为什么Comparator.comparing不能与String :: toLowerCase方法引用一起使用?


我试图尽可能地减少这个问题。 特别是,我已经删除了几乎所有依赖项到其他类。 main方法包含两个方法调用。 第一个语句编译时没有错误,而第二个语句产生错误。

 interface Fun { R apply(T t); } public final class Foo { public static void main(String... args) { invoke(Foo::bar); // OK invoke(Foo::baz); // ERROR } private static  void invoke(Fun f) { } private String bar() { return null; } private String baz() { return null; } private String baz(Integer i, Integer j) { return null; } } 

这很奇怪,因为第二个baz方法不应该适用于这种情况,因为参数的数量不匹配。 我看过JLS8(15.13)。 但是,没有任何帮助,因为方法引用的规则非常复杂。

问:为什么第二种情况会出现编译错误? 根据JLS真的会出现编译错误吗? 根据对另一个问题的一些评论,Netbeans中没有编译错误。


作为参考,我使用的是JDK8版本1.8.0-b132。 如果在命令行上编译程序,编译器将显示以下错误消息:

 $ /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 invoke(Fun) U extends Object declared in method invoke(Fun) Foo.java:6: error: invalid method reference invoke(Foo::baz); // ERROR ^ non-static method baz() cannot be referenced from a static context 2 errors 

JLS8(15.13)令人困惑,但它确实显示了类似于你的例子,说明它们在搜索中的含糊不清,无法解决。

对于你的例子,Intellij说invoke(Foo::baz); 是一个循环推理我认为它更多地与invoke需要推断类型以及Foo::baz

这可以通过为invoke函数赋予类型来解决,类似于JSL(15.13.1示例)

搜索足够智能,可以忽略所有适用方法(来自两个搜索)都是实例方法的歧义:

Foo.invoke(Foo::baz); – 相当于, 我想使用Foovoid方法返回一个String aka String baz()

 interface Fun { R apply(T t); } interface Fun2 { R apply(T t, U u); } public final class Foo { public static void main(String... args) { invoke(Foo::bar); // OK Foo.invoke(Foo::baz); // NO ERROR Fun2 f2 = Foo::baz; // Overloaded method baz } private static  void invoke(Fun f) { } private String bar() { return null; } private String baz() { return null; } private String baz(Integer i) { return null; } } 

我同意你的看法, baz(Integer i)不是一个有效的参数,无需invoke它就可以将其设置为静态或来自Foo的实例。 我想搜索算法只是在方法过载并且它试图推断出类型时才退出。 因为它只使用一个方法签名。