尝试编译表达式Comparator.comparing(String::toLowerCase)
时,Java编译器会返回错误。有关更多信息,请参阅以下问题:
Why Comparator.comparing doesn't work with String::toLowerCase method reference?
我试图尽可能地减少问题。特别是,我已经删除了几乎所有依赖项到其他类。 main 方法包含两个方法调用。第一个语句编译时没有错误,而第二个语句产生错误。
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; }
}
这很奇怪,因为第二个 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 <T,U>invoke(Fun<T,U>)
U extends Object declared in method <T,U>invoke(Fun<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
答案 0 :(得分:5)
JLS8 (15.13)令人困惑,但它确实显示了与您类似的示例,说明它们在搜索中无法解决的含糊之处。
对于你的例子,Intellij说invoke(Foo::baz);
是一个循环推理 我认为更多地与invoke
需要推断的组合有关类型以及Foo::baz
。
这可以通过给invoke
函数赋予类型来解决,类似于JSL(15.13.1示例)
搜索足够智能,可以忽略所有适用方法(来自两个搜索)都是实例方法的歧义:
Foo.<Foo,String>invoke(Foo::baz);
- 相当于,我想使用返回void
又名Foo
的{{1}} String
方法}
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> void invoke(Fun<T, U> f) { }
private String bar() { return null; }
private String baz() { return null; }
private String baz(Integer i) { return null; }
}
不是baz(Integer i)
的有效参数,不能使其成为静态参数或来自invoke
的实例。我想搜索算法只是在方法过载并且它试图推断出类型时才退出。因为它只使用一个方法签名。