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;
}
精彩评论