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

use*_*428 4 java generics interface comparable

所以我有一个实现Comparable的类(为了简洁我在这里有一个虚拟方法)

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

另一个类中的方法采用Comparable(再次,虚拟方法)

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

然而,当我尝试按如下方式调用我的方法时

int index = ArrayOps.binSearch(entries, newEntry);
Run Code Online (Sandbox Code Playgroud)

其中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.
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?MarkovEntry专门实现了Comparable - 为什么编译器不能识别?

我的类Chainable也实现了Comparable,以防它与它有任何关系.

awk*_*ksp 5

泛型在这方面有点奇怪

ArrayList<SuperType>
Run Code Online (Sandbox Code Playgroud)

实际上并不是超类型

ArrayList<SubType>
Run Code Online (Sandbox Code Playgroud)

例如ArrayList<Number>,不是超类型ArrayList<Integer>.这是因为如果这样的关系举行,你可以在替换ArrayList<Number>ArrayList<Integer>,那么这将允许本来是非法的,如果你没有做的替换操作.

更具体地说,你说这样做:

ArrayList<Number> list = new ArrayList<Integer>();
Run Code Online (Sandbox Code Playgroud)

那么你可以把一个Double进入list,因为编译器,list是一个ArrayList<Number>!正如您所看到的,这打破了泛型应该提供的保证,因此不允许这样做.


您正在寻找的是这样的通用方法:

public static <T extends Comparable<? super T>> int binSearch(ArrayList<T> list)
Run Code Online (Sandbox Code Playgroud)

基本上,您可以使用与生成类相同的方法来生成方法.

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

  • 这里不需要通用方法; 只需使用[通配符](http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html):`int binarySearch(ArrayList <?extends Comparable> list)` (2认同)