java - 为什么这个 Java 方法调用被认为是不明确的?

标签 java overloading method-reference functional-interface arity

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

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() 的调用没问题,正如预期的那样,我无法将方法引用同时分配给 SupplierProcessor,因为它没有歧义: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 不同,我无法分配方法引用SupplierProcessor。如果它真的不明确,我觉得我应该能够将 s3p3 分配给两个重载参数类型,就像在 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/

相关文章:

lambda - 组合对特定类型的任意对象的实例方法的引用

java - 使用 Stream 避免 NoSuchElementException

julia - 是否可以从 Julia 中的覆盖函数中调用重载函数?

c++ - 运算符 = 使用模板重载

java - 方法引用与 lambda 表达式

java - 方法引用 ↔ lambda 等价

java - 将 HTTP 响应(Java "Properties"流格式)转换为 NSDictionary

java - Android - 以编程方式向 Activity 添加关键监听器

java - 是否可以使用Java创建dll?

java - 在 Java 接口(interface)中重新定义等待方法