我遇到了一条奇怪的错误消息,我认为它可能不正确。考虑以下代码:
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
),但与 Exhibit A 不同,我无法分配方法引用Supplier
和 Processor
。如果它真的不明确,我觉得我应该能够将 s3
和 p3
分配给两个重载参数类型,就像在 Exhibit A 中一样,但是我在 p3
指出 错误:类型不兼容:方法引用无效
。图表 C 中的第二个错误是有道理的,Overloaded::strangelyAmbiguous
不可分配给 Processor
,但如果不可分配,为什么它仍然被认为是模棱两可的吗?
在确定选择哪个重载版本时,方法引用推理似乎只查看 FunctionalInterface 的参数。在变量赋值时,会检查参数的个数和类型,这导致了重载方法和变量赋值之间的这种差异。
在我看来这像是一个错误。如果不是,至少错误消息是不正确的,因为在两个选择之间只有一个是正确的时可以说没有歧义。
最佳答案
您的问题与this 非常相似一个。
简短的回答是:
Overloaded::genuinelyAmbiguous;
Overloaded::notAmbiguous;
Overloaded::strangelyAmbiguous;
所有这些方法引用都是不准确的(它们有多个重载)。因此,根据 JLS §15.12.2.2. ,它们会在重载解析期间从适用性检查中跳过,这会导致歧义。
在这种情况下,您需要明确指定类型,例如:
load((Processor) Overloaded::genuinelyAmbiguous);
load(( Supplier) Overloaded::strangelyAmbiguous);
关于java - 为什么这个 Java 方法调用被认为是不明确的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57118216/