方法引用中存在歧义

问题描述 投票:0回答:1

考虑以下代码片段:

public static void main(String[] args) {
        Function<String, String> function = String::toUpperCase;        //OK
//        Comparator<String> comparator = String::toUpperCase;          //Compilation error(makes sense, as String.toUpperCase(Locale locale) & String.toUpperCase() are not compatible)
        fun(String::toUpperCase);                                       // java: reference to fun is ambiguous
    }

    public static void fun(Function<String, String> function) { // String apply(String obj)
        System.out.println("Function");
    }

    public static void fun(Comparator<String> comparator) {     // int compare(String s1, String s2)
        System.out.println("Comparator");
    }

我无法理解方法调用歧义错误背后的原因

fun(String::toUpperCase)

由于

String::toUpperCase
本身的两个重载版本与 Comparator 类中的
int compare(String s1, String s2)
不兼容,那么编译器为什么首先会抱怨歧义呢?

我在这里遗漏了什么吗?

java lambda java-8 method-reference ambiguity
1个回答
0
投票

toUpperCase
有一个不带参数的重载,以及另一个带一个参数的重载 (
Locale
)。

这使得表达式

String::toUpperCase
成为 inexact 方法引用表达式。该表达式可以指无参数重载,也可以指单参数重载。

两个

fun
都被确定为“潜在适用”,特别是因为这个条款:

  • 方法引用表达式可能与功能接口类型兼容

    T
    如果,其中
    T
    的函数类型为 n,则至少存在一个潜在的 当方法引用表达式的目标是时适用的方法 元数为 n 的函数类型,且满足以下条件之一:

    • 方法引用表达式的形式为
      ReferenceType :: [TypeArguments] Identifier
      和至少一个可能适用的 方法要么是 (i) 静态并支持数量 n,要么 (ii) 非静态 并支持数量 n-1。
    • [无关]

String::toUpperCase
可能与
Function<String, String>
兼容,因为
Function<String, String>
的元数为 1(采用一个参数),并且
toUpperCase
是非静态的并且具有无参数重载。

String::toUpperCase
可能与
Comparator<String>
兼容,因为
Comparator<String>
的元数为 2,并且
toUpperCase
是非静态的并且具有单参数重载。请注意,此步骤根本不检查参数类型或返回类型。参数类型是
Locale
并不重要,但实际上需要
String

找到潜在适用的方法后,我们继续通过严格调用识别适用的匹配数量方法。这就是出问题的地方。还记得

String::toUpperCase
是如何成为 inexact 方法引用的吗?这意味着它与适用性无关 - 编译器在此步骤中根本不考虑方法引用。另请参阅另一个问题,该问题还涉及导致重载解析错误的不精确方法引用表达式。

因此,两个

fun
都可以通过严格调用来应用。下一步是找到最具体的方法。此步骤考虑子类型,例如
String
Object
更具体。但是
Comparator<String>
Function<String, String>
无关,所以我们找不到的具体方法,就会出现错误。

© www.soinside.com 2019 - 2024. All rights reserved.