开发者

What is the problem with this Java code dealing with 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() {
        r开发者_如何学编程eturn element.add(element.zero());
    }
}

It seems that element.add() doesn't return an E extends Addable but rather an Object. Why is that? Has it anything to do with Java not knowing at run-time what the object types really are, so it just assumes them to be Objects(thus requiring a cast)?

Thanks


Try:

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

I don't know if this is exactly what you mean but basically the problem is that you're using Addable in the declaration of SumSet as a raw type. That strips off all generic parameter types and makes Addable appear to SumSet as:

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

Obviously Object is not an E, hence the error. See What is the raw type? from the Java Generics FAQ.

On a side note public is unnecessary on methods in interface definitions.


It should be:

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

Your original code specifies that each element of SumSet must be an instance of E, a class that implements Addable (which is equivalent to Addable<Object>). By changing Addable to Addable<E>, you're specifying that add, sub, and zero methods of the E class must accept and return instances of E (rather than just Object).

Note that the E type variable in SumSet has nothing to do with the above E variable. So:

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());
    }
}

works fine too.


You need to say <E extends Addable<E>>, not <E extends Addable>.

This is because when using a raw type, all references to its (non-existent) type parameters get erased.


Rather than creating a SumSet class that implements Set, you might want to consider whether you can get what you need by writing a method that can sum all of the elements in the set.

public static <T extends Addable<T> > T sum(Set<T> set)
{
    T sum = null;
    for (T t : set)
    {
        if (sum == null)
        {
            sum = t;
        }
        else
        {
            sum = sum.add(t);
        }
    }
    return sum;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜