使用类型集合时编译错误对方法的模糊引用

时间:2014-12-28 18:30:59

标签: java

在同一个类中,我有两个重载方法:

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,java.util.Collection)匹配

我在第二个参数中传递了一个集合,所以为什么编译器不知道 转到第二种方法?
如果我改变方法签名并从第一个参数中删除泛型我将 没有得到编译错误,为什么会这样?

3 个答案:

答案 0 :(得分:3)

这是我的解释。当编译器必须在重载之间进行选择时,它总是选择最具体的重载。从第一个参数中删除类型信息时,签名变为

public static <T> void foo(Collection collection, T valueToAppend)
public static <T> void foo(Collection collection, Collection<T> valueToAppend)

其中第二个更具体。第一种方法也可以接受第二种方法可以接受的任何参数对,因为任何Collection都是Object。因此,当您去除类型参数时,没有歧义 - 如果您传递两个Collection,则选择第二种方法。

但是对于类型信息,签名如下所示:

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>()将被第二个签名接受,但不会被第一个签名接受。

因此,如果两个签名都适用,则存在问题。

您正在尝试传递原始ArrayListList<Double>。由于您使用的是原始类型ArrayList(您永远不应该这样做),ftList可以作为任何 Collection<T>的{​​{1}}传递(尝试尝试将原始T传递给参数类型为List的方法。它可以工作)。因此,您只需要看到List<String>两个重载的第二个参数匹配。如果doubleListT,则匹配第一个签名,如果List<Double>T则匹配第二个签名。

答案 1 :(得分:0)

由于第二个参数<T>也可能是Collection,因此解释者会感到困惑,无论是Collection<T>还是<T>

答案 2 :(得分:0)

编译器无法识别<T>Collection<T>