Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the problem with this Java code dealing with Generics?

Tags:

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

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

like image 222
devoured elysium Avatar asked Apr 17 '10 03:04

devoured elysium


2 Answers

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.

like image 157
cletus Avatar answered Sep 25 '22 19:09

cletus


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.

like image 45
Matthew Flaschen Avatar answered Sep 22 '22 19:09

Matthew Flaschen