编译器认为可比较类型不可比较。

4

所以我有一个实现了Comparable接口的类(这里只为简洁起见提供了一个虚拟方法)

public class MarkovEntry<T extends Chainable> implements Comparable<MarkovEntry<T>>
{
    // Compare two rows by ID
    public int compareTo(MarkovEntry<T> e)
    {
        return 0;
    }
}

另一个类中有一个方法接受一个 Comparable(再次强调,这只是一个虚拟方法)。

public class ArrayOps
{
    public static int binSearch(ArrayList<Comparable> list, Comparable c)
    {
        return 0;
    }
}

当我尝试以以下方式调用我的方法时:
int index = ArrayOps.binSearch(entries, newEntry);

如果entries是一个MarkovEntry的ArrayList,newEntry是一个MarkovEntry,编译器会告诉我

actual argument java.util.ArrayList<com.company.MarkovEntry<T>> cannot be converted 
to java.util.ArrayList<java.lang.Comparable> by method invocation.

这里发生了什么事情?MarkovEntry明确实现了Comparable,为什么编译器没有识别出来?
我的类Chainable也实现了Comparable,如果这有任何关系的话。
1个回答

5

泛型有些奇怪,因为

ArrayList<SuperType>

实际上不是超类型的

ArrayList<SubType>

例如,ArrayList<Number> 不是 ArrayList<Integer> 的超类型。这是因为如果存在这样的关系,你可以将一个 ArrayList<Number> 替换为一个 ArrayList<Integer>,这将允许执行在没有替换时会非法的操作。
更具体地说,假设你这样做:
ArrayList<Number> list = new ArrayList<Integer>();

那么你就能够将一个Double放入list中,因为对于编译器来说,list是一个ArrayList<Number>!正如你所见,这违反了泛型应该提供的保证,因此是不允许的。


你需要的是这样的一个泛型方法

public static <T extends Comparable<? super T>> int binSearch(ArrayList<T> list)

基本上,你可以像泛型类一样泛型方法。

更多信息可在此处找到:http://docs.oracle.com/javase/tutorial/extra/generics/methods.html


2
这里不需要一个通用方法;只需使用一个通配符:int binarySearch(ArrayList<? extends Comparable> list) - fabian
等等,Comparable 不需要加参数吗? - awksp
1
为了获得最佳结果,请使用<T extends Comparable<? super T>> - newacct
binSearch(ArrayList<? extends Comparable<?>> list) 不会是类型安全的。 - newacct
@newacct 我知道有什么东西遗漏了...谢谢! - awksp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接