繁体   English   中英

参数中带有通配符的歧义重载泛型方法

[英]Ambiguous overloaded generic method with wildcard in parameter

鉴于以下声明

interface Base<A> { }

interface Special<A,B> extends Base<A> { }

<T> void foo(Base<T> b) {}

<T> void foo(Special<?,T> s) {}

为什么我得到以下代码的编译错误:

Special<String, Integer> s = null;
foo(s); // error: reference to foo is ambiguous

顺便说一句,可以通过将第二种方法的声明更改为

<T,X> void foo(Special<X,T> s) {}

首先,一个非常有趣的问题。

没有泛型

考虑以下代码:

interface NoGenericsBase { }

interface NoGenericsSpecial extends NoGenericsBase { }

interface NoGenericsSuperSpecial extends NoGenericsSpecial { }

void foo(NoGenericsBase b) {
    System.out.println("Feel tha base");
}

void foo(NoGenericsSpecial s) {
    System.out.println("Special delivery");
}

我们一直被教导编译器会选择最具体的方法 实际上,如果您调用foo((NoGenericsSuperSpecial) null) ,上述代码将打印以下内容:

特快专递

到目前为止,一切都很好。

泛型

现在,让我们测试一些泛型行为:

interface Base<T> { }

interface Special<T> extends Base<T> { }

void foo(Base<? extends Number> b) {
    System.out.println("Feel tha base");
}

void foo(Special<? extends Number> s) {
    System.out.println("Special delivery");
}

public static void main(String[] args) {
    Special<Integer> v = null;
    new Main().foo(v);
}

这段代码会编译。 编译器找到两个匹配项–都为Base<? extends Number> Base<? extends Number>Special<? extends Number> Special<? extends Number> apply –,但是编译器能够找出最具体的哪个:它将选择void foo(Special<? extends Number>) ,因为未绑定通配符的两个捕获都相等。

但是让我们重写foo(Base<...>)方法并保持其余的不变:

void foo(Base<? extends Integer> b) {
    System.out.println("Feel tha base");
}

现在出现以下错误:

对foo的引用不明确
方法foo(Base<? extends Integer>)和方法foo(Special<? extends Number>)匹配

在找出最具体的类型匹配之前,编译器会处理类型变量。 显然, 编译器无法弄清楚是否<? extends Number> <? extends Number><? extends Integer> <? extends Integer>适用,而不管变量本身的类型BaseSpecial )。

似乎变量类型处理先于关于继承的方法签名的选择。

一个(或者至少我本人)应该期望编译器选择foo(Special<? extends Number>) ,但是事实并非如此。

原因

我不知道编译器是否无法选择关于泛型的最具体的编译器,或者是否未配置成这样做。

有关更多详细信息,请参见Java语言规范§18.5§4.5.1

让我花一些时间阅读更多泛型,以便也许我们能弄清楚...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM