在同一个类中,我有两种重载方法:
public static <T> void foo(Collection<T> collection, T valueToAppend);
public static <T> void foo(Collection<T> collection, Collection<T> valueToAppend);
以下测试应调用第二种方法:
@Test
public void testFoo() {
ArrayList ftList = Lists.newArrayList();
List<Double> doubleList = Lists.newArrayList(1.0, 2.0);
foo(ftList, doubleList);
}
当我运行测试时,出现以下编译错误:
对foo的引用是不明确的,path.to.class中的方法foo(java.util.Collection,T)和path.to.class中的方法foo(java.util.Collection,T)都匹配。
我在第二个参数中传递了一个集合,那么为什么编译器不知道要使用第二种方法?
如果我更改方法签名并从第一个参数中删除泛型,我将不会得到编译错误,那是为什么?
这是我的解释。当编译器必须在重载之间进行选择时,它总是选择最具体的重载。当您从第一个参数中删除类型信息时,签名变为
public static <T> void foo(Collection collection, T valueToAppend)
public static <T> void foo(Collection collection, Collection<T> valueToAppend)
其中的第二个更为具体。第二种方法可以接受的任何一对参数也可以被第一种方法接受,因为anyCollection
是一个Object
。因此,当您将类型参数剥离时,没有歧义-如果您传递两个Collection
s,则选择第二种方法。
但是,使用类型信息,签名如下所示:
public static <T> void foo(Collection<T> collection, T valueToAppend)
public static <T> void foo(Collection<T> collection, Collection<T> valueToAppend)
这些签名中的任何一个都不比另一个更具体。参数new ArrayList<String>()
和"Foo"
将被第一个签名接受,但第二个签名不接受。参数new ArrayList<String>()
和new ArrayList<String>()
将被第二个签名接受,但第一个签名不接受。
因此,如果两个签名均适用,则存在问题。
您正在尝试传递原始字符ArrayList
和原始字符List<Double>
。由于您使用的是原始类型ArrayList
(你应该永远不会做),ftList
可以通过一个Collection<T>
对任何 T
(尝试它。请尝试将原料List
与类型的参数的方法List<String>
。它的工作原理)。因此,您只需要看到两个重载都doubleList
与第二个参数匹配。它的第一个签名,如果匹配的是与第二签名匹配,如果是。T
List<Double>
T
Double
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句