处理泛型的Java代码有什么问题?

时间:2010-04-17 03:40:49

标签: java generics

interface Addable<E> {
    public E add(E x);
    public E sub(E y);
    public E zero();
}

class SumSet<E extends Addable> implements Set<E> {

    private E element;

    public SumSet(E element) {
        this.element = element;
    }

    public E getSum() {
        return element.add(element.zero());
    }
}

似乎element.add()不会返回E extends Addable而是Object。这是为什么?它与Java有什么关系,在运行时不知道对象类型到底是什么,所以它只是假设它们是对象(因此需要强制转换)?

由于

4 个答案:

答案 0 :(得分:9)

尝试:

class SumSet<E extends Addable<E>> implements Set<E> {

我不知道这是不是你的意思,但基本上问题是你在Addable的声明中使用SumSet作为原始类型。这剥离了所有通用参数类型,并使Addable显示为SumSet

interface Addable {
  Object add(Object x);
  Object sub(Object y);
  Object zero();
}

显然Object不是E,因此错误。请参阅Java Generics FAQ中的What is the raw type?

在旁注中,public对于接口定义中的方法是不必要的。

答案 1 :(得分:5)

应该是:

class SumSet<E extends Addable<E>> implements Set<E> {

您的原始代码指定SumSet的每个元素必须是E的实例,即实现Addable的类(相当于Addable<Object>)。通过将Addable更改为Addable<E>,您将指定E类的add,sub和zero方法必须接受并返回E的实例(而不仅仅是Object)。

请注意,SumSet中的E类型变量与上述E变量无关。所以:

class SumSet<T extends Addable<T>> implements Set<T> {

    private T element;

    public SumSet(T element) {
        this.element = element;
    }

    public T getSum() {
        return element.add(element.zero());
    }
}

也可以。

答案 2 :(得分:3)

您需要说<E extends Addable<E>>,而不是<E extends Addable>

这是因为在使用原始类型时,对其(不存在的)类型参数的所有引用都将被删除。

答案 3 :(得分:0)

您可能想要考虑是否可以通过编写可以对集合中所有元素求和的方法来获得所需内容,而不是创建实现SumSet的{​​{1}}类。

Set