简体   繁体   English

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

[英]Compilation error ambiguous reference to method when using typed collection

In the same class i have two overloading methods: 在同一个类中,我有两个重载方法:

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

The following test should call The second method: 以下测试应调用第二种方法:

 @Test 
   public void testFoo() {
   ArrayList ftList = Lists.newArrayList();
   List<Double> doubleList = Lists.newArrayList(1.0, 2.0);
   foo(ftList, doubleList);
}

When i run the test i get the following compilation error: 当我运行测试时,我得到以下编译错误:

reference to foo is ambiguous, both method foo(java.util.Collection,T) in path.to.class and method foo(java.util.Collection,java.util.Collection) in path.to.class match. 对foo的引用是不明确的,path.to.class中的方法foo(java.util.Collection,T)和path.to.class中的方法foo(java.util.Collection,java.util.Collection)都匹配。

I'm passing a collection in the second argument so why doesn't the compiler know to go to the second method? 我在第二个参数中传递一个集合,那么编译器为什么不知道转到第二个方法呢?
If i change the methods signature and remove the generics from the first parameter i will not get compilation error, why is that? 如果我更改方法签名并从第一个参数中删除泛型我不会得到编译错误,为什么会这样?

Here is my explanation. 这是我的解释。 When the compiler has to choose between overloadings, it always chooses the most specific overloading. 当编译器必须在重载之间进行选择时,它总是选择最具体的重载。 When you strip the type information from the first parameter, the signatures become 从第一个参数中删除类型信息时,签名将变为

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

The second of these is more specific. 其中第二个更具体。 Any pair of parameters that can be accepted by the second method can also be accepted by the first, because any Collection is an Object . 第一种方法可以接受的任何参数对也可以被第一种方法接受,因为任何Collection都是Object Therefore when you strip the type parameter away, there is no ambiguity - the second method is chosen if you pass two Collection s. 因此,当您去除类型参数时,没有歧义 - 如果您传递两个Collection则选择第二种方法。

However with the type information, the signatures look like this: 但是,对于类型信息,签名如下所示:

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

Neither of these signatures is more specific than the other. 这些签名都没有比另一个更具体。 The parameters new ArrayList<String>() and "Foo" will be accepted by the first signature but not the second. new ArrayList<String>()"Foo"将被第一个签名接受,但不会被第二个签名接受。 The parameters new ArrayList<String>() and new ArrayList<String>() will be accepted by the second signature but not the first. new ArrayList<String>()new ArrayList<String>()将被第二个签名接受,但不会被第一个签名接受。

So if both signatures apply, there is a problem. 因此,如果两个签名都适用,则存在问题。

You are trying to pass a raw ArrayList and a List<Double> . 您正在尝试传递原始ArrayListList<Double> Because you are using a raw type ArrayList (which you should never do), ftList can pass as a Collection<T> for any T (Try it. Try passing a raw List to a method with parameter of type List<String> . It works). 因为您使用的是原始类型ArrayList (您永远不应该这样做), ftList可以作为任何 TCollection<T>传递(尝试它。尝试将原始List传递给参数类型为List<String> 。作品)。 Therefore you only need to see that doubleList matches the second parameter for both overloadings. 因此,您只需要看到doubleList两个重载的第二个参数匹配。 It matches the first signature if T is List<Double> and matches the second signature if T is Double . 它的第一签名相匹配,如果TList<Double>和第二签名,如果匹配TDouble

因为第二个参数<T>也可以是一个Collection ,所以解释器会混淆它是Collection<T>还是<T>

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

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

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