我遇到了一个奇怪的错误信息,我认为它可能是错误的。请考虑以下代码:
public class Overloaded {
public interface Supplier {
int get();
}
public interface Processor {
String process(String s);
}
public static void load(Supplier s) {}
public static void load(Processor p) {}
public static int genuinelyAmbiguous() { return 4; }
public static String genuinelyAmbiguous(String s) { return "string"; }
public static int notAmbiguous() { return 4; }
public static String notAmbiguous(int x, int y) { return "string"; }
public static int strangelyAmbiguous() { return 4; }
public static String strangelyAmbiguous(int x) { return "string"; }
}
如果我有一个长成这样的方法:
// Exhibit A
public static void exhibitA() {
// Genuinely ambiguous: either choice is correct
load(Overloaded::genuinelyAmbiguous); // <-- ERROR
Supplier s1 = Overloaded::genuinelyAmbiguous;
Processor p1 = Overloaded::genuinelyAmbiguous;
}
我们得到的错误是很有道理的; load()
的参数可以分配给任何一个, 所以我们会得到一个声明方法调用不明确的错误。
相反,如果我有一个看起来像这样的方法:
// Exhibit B
public static void exhibitB() {
// Correctly infers the right overloaded method
load(Overloaded::notAmbiguous);
Supplier s2 = Overloaded::notAmbiguous;
Processor p2 = Overloaded::notAmbiguous; // <-- ERROR
}
load()
的调用很好,正如预期的那样,我不能将该方法引用分配给Supplier
和Processor
,因为它不是模糊的:Overloaded::notAmbiguous
不能赋值给p2
。
现在是一个奇怪的例子。如果我有这样一个方法:
// Exhibit C
public static void exhibitC() {
// Complains that the reference is ambiguous
load(Overloaded::strangelyAmbiguous); // <-- ERROR
Supplier s3 = Overloaded::strangelyAmbiguous;
Processor p3 = Overloaded::strangelyAmbiguous; // <-- ERROR
}
编译器抱怨调用 load()
方法是不明确的(error: reference to load is ambiguous
),但与A展示不同的是,我无法将方法引用分配给 Supplier
和 Processor
。如果它真的是不确定的话,我感觉应该像在A展示中一样能够将s3
和p3
分配给两个重载参数类型,但是我在 p3
上得到一个错误,指出error: incompatible types: invalid method reference
。在C展示中的这第二个错误是有道理的,因为Overloaded::strangelyAmbiguous
无法被分配给 Processor
,但如果它无法被分配,为什么它仍然被认为是模棱两可的呢?看起来方法引用推断仅在函数接口的 arity 决定哪个重载版本要选择时才会看。在变量分配时,根据参数的数量和类型都会进行检查,这导致了在重载方法和变量分配之间存在差异。
对我来说,这似乎是一个缺陷。如果不是的话,至少错误消息是不正确的,因为在两个选择之间只有一个是正确的时候,可以说不存在歧义。
loadProcessor
和loadSupplier
这样的名称,这样我就不必思考它们的含义了。 - markspace