为什么我们会出现两个错误的解释是方法引用Integer::toString可以作为参考
以下 sn-ps 应该演示编译器在两种情况下为 Integer::toString 选择的内容。
将选择实例方法i.toString()
static class MyInteger {
int value;
public MyInteger(int i) {
this.value = i;
}
public String toMyString() {
return "instance " + value;
}
}
Stream<MyInteger> stream = ...
stream.map(MyInteger::toMyString).forEach(System.out::println);
/* which would be equivalent to
stream.map(new Function<MyInteger, String>() {
public String apply(MyInteger t) {
return t.toMyString();
}
});
// as method argument for stream.map() the compiler generates
invokevirtual MyInteger.toMyString:()Ljava/lang/String;
*/
将选择静态方法Integer.toString(i)
static class MyInteger {
int value;
public MyInteger(int i) {
this.value = i;
}
public static String toMyString() {
return "static " + value;
}
}
Stream<MyInteger> stream = ...
stream.map(MyInteger::toMyString)..forEach(System.out::println);
/* which would be equivalent to
stream.map(new Function<MyInteger, String>() {
@Override
public String apply(MyInteger t) {
return MyInteger.toMyString(t);
}
});
// as method argument for stream.map() the compiler generates
invokestatic MyInteger.toMyString:(LMyInteger;)Ljava/lang/String;
*/
在第一遍中,解析器尝试找到可以在对象实例上调用的方法。因为toMyString() 和toMyString(MyInteger) 两种方法都可以在MyInteger 类型的对象上调用,并且都满足Function<? super T,? extends R> 的要求,所以我们得到第一个错误reference to toString is ambiguous。
(见源:com.sun.tools.javac.comp.Resolve.mostSpecific(...))。
在第二遍中,解析器试图找到一个静态方法toString。由于对(先前解决的)方法toString() 的引用不是静态的,我们得到第二个错误non-static method toString() cannot be referenced from a static context。
(见源:com.sun.tools.javac.comp.Resolve.resolveMemberReference(...))。
edit 一个小例子来解释这两个错误的原因。 javac 的解析器无法知道您在 Integer::toString 上的意图。您的意思可能是i.toString() 或Integer.toString(i),所以他对这两种情况都进行了验证。这也是他在其他情况下的工作方式。
举个例子:
class Foo {
int x + y = 1;
}
报告的错误是
Scratch.java:2: error: ';' expected
int x + y = 1;
^
Scratch.java:2: error: <identifier> expected
int x + y = 1;
^
在这个小 sn-p 中,解析器也不知道你的意图是什么。看到一些可能性。
int x; y = 1; // missed the semicolon and the declaration for `y`
int x = y = 1; // typo at `+`
int x = y + 1; // swapped `+` and `=` and missed declaration of `y`
... more possibilities exist
在这种情况下,解析器也不会在第一个错误之后立即停止。