无界Java通用接口的问题

时间:2011-08-19 07:46:55

标签: java generics interface abstract

考虑以下简单代码

import java.util.*;

public class MainTest<T extends Object1<?,?>> {
    List<T> list;

    public MainTest(List<T> l) {
        this.list=l;
    }
    public int testCompare() {
        // fails to compile here
        return list.get(0).compareTo(list.get(1));
    }

    public static void main(String[]args) {
        List<Object1Impl> list = new ArrayList<Object1Impl>();
        list.add(new Object1Impl());
        list.add(new Object1Impl());

        MainTest<Object1Impl> test = new MainTest<Object1Impl>(list);
        System.out.println(test.testCompare());
    }
}

interface Object1<E, V> extends Comparable<Object1<E,V>> { }
class Object1Impl implements Object1<Integer, Integer>{
    public int compareTo(Object1<Integer, Integer> o) { return 0; }
}

我知道在这种情况下程序不会编译(在testCompare()失败,因为T正在扩展无界Object1<?,?>)。除了制作MainTest<T extends Object1<E,V>,E,V>之外,还有其他方法可以解决这个问题吗?

编辑:错误消息是

The method compareTo(Object1<capture#1-of ?,capture#2-of ?>) in the type Comparable<Object1<capture#1-of ?,capture#2-of ?>> is not applicable for the arguments (T)

我读过有效的Java书,但仍然无法真正想到解决方案..

另外,为什么如果我将接口Object1更改为抽象类,程序将编译没有任何问题?这真让我感到困惑......

编辑:当我的意思是改为抽象类时如下

abstract class Object1<E, V> implements Comparable<Object1<E,V>>{ 
    public int compareTo(Object1<E,V> o) { return 0; }
}

class Object1Impl extends Object1<Integer, Integer>{ }

这将有效(只有使用Eclipse,使用javac手动编译它不起作用)但我不知道为什么

1 个答案:

答案 0 :(得分:4)

这是正确的;编译器无法验证list.get(0)list.get(1)是否属于同一类型;一个可能是Object1<String, Integer>而另一个Object1<BigDecimal, Double>

要确保它们属于同一类型,您必须绑定这些类型:

public class MainTest<A,B,T extends Object1<A,B>> {
    List<T> list;

    public MainTest(List<T> l) {
        this.list=l;
    }
    public int testCompare() {
        // fails to compile here
        return list.get(0).compareTo(list.get(1));
    }

    public static void main(String[]args) {
        List<Object1Impl> list = new ArrayList<Object1Impl>();
        list.add(new Object1Impl());
        list.add(new Object1Impl());

        MainTest<Integer, Integer, Object1Impl> test = new MainTest<Integer, Integer, Object1Impl>(list);
        System.out.println(test.testCompare());
    }
}

据我所知,Java不允许将参数类型绑定到类而没有特别指定它们。