为什么将此Java方法调用视为模棱两可?

jig*_*wot 15 java overloading arity functional-interface method-reference

我遇到了奇怪的错误消息,我认为这可能是不正确的。考虑以下代码:

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"; }
}
Run Code Online (Sandbox Code Playgroud)

如果我有一个看起来像这样的方法:

// Exhibit A
public static void exhibitA() {
    // Genuinely ambiguous: either choice is correct
    load(Overloaded::genuinelyAmbiguous); // <-- ERROR
    Supplier s1 = Overloaded::genuinelyAmbiguous;
    Processor p1 = Overloaded::genuinelyAmbiguous; 
}
Run Code Online (Sandbox Code Playgroud)

我们得到的错误是很合理的;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
}
Run Code Online (Sandbox Code Playgroud)

的调用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
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨对的调用load()是模棱两可的(error: reference to load is ambiguous),但与图表A不同,我无法将方法引用分配给SupplierProcessor。如果确实是模棱两可,我觉得我应该能够像在表A中一样分配s3和分配p3这两种重载的参数类型,但是在p3声明这一点时出现错误error: incompatible types: invalid method reference。图表C中的第二个错误是有道理的,Overloaded::strangelyAmbiguous 不可分配给Processor,但如果不可分配,为什么仍被认为是模棱两可的?

在确定选择哪个重载版本时,方法引用推断似乎只考虑了FunctionalInterface的优点。在变量分配中,将检查参数的稀疏性类型,这会导致重载方法与变量分配之间出现差异。

在我看来,这就像一个虫子。如果不是,则至少错误消息是不正确的,因为在两个选择之间只有一个是正确的时,可以说没有歧义。

Ole*_*hov 6

您的问题与非常相似。

简短的答案是:

Overloaded::genuinelyAmbiguous;
Overloaded::notAmbiguous;
Overloaded::strangelyAmbiguous;
Run Code Online (Sandbox Code Playgroud)

所有这些方法引用都不精确(它们有多个重载)。因此,根据JLS§15.12.2.2。,则会在重载解决期间将其从适用性检查中跳过,从而造成歧义。

在这种情况下,您需要明确指定类型,例如:

load((Processor) Overloaded::genuinelyAmbiguous);
load(( Supplier) Overloaded::strangelyAmbiguous);
Run Code Online (Sandbox Code Playgroud)