I have some problem with generics, let me explain.
I have a class which wraps a LinkedList:
public class IdnList<T extends Numerable> extends IdnElement implements List<T> {
private LinkedList<T> linkedList;
@Override
public boolean add(T e){
return linkedList.add(e);
}
//stuff
}
please note that the generic type T of this class extends the Numerable interface.
Ok, now inside a different class I want to invoke this method as follows:
if(childToAdd instanceof Numerable)
((IdnList<?>)this).add((Numerable)childToAdd);
but eclipse says: The method add(capture#1-of ?) in the type IdnList<capture#1-of ?> is not applicable for the arguments (Numerable), and I really can’t figure out why it can’t work. Why can’t I add a Numerable object to my list?
What am I missing?
EDIT:
it’s a classic. You ask, and then you find a clue. It seems a workaround is:
((IdnList<Numerable>)this).add((Numerable)childToAdd);
but I don’t know how elegant it is. I really appreciate further comments.
Say you have classes
AandBthat both extendNumerable. Then there are three valid types ofIdnList:IdnList<A>,IdnList<B>, andIdnList<Numerable>.I hope you would agree that you shouldn’t be able to add any
Numerableto anIdnList<A>.Now, in this line of code, how does the compiler know whether you’ve matched up the types correctly?
All it knows is that
childToAddis aNumerable, and thatthisis some kind ofIdnList. It doesn’t know what kind, so it can’t guarantee type safety. Remember that generic type checking is done entirely at compile time, not runtime.I see how the workaround allows the code to compile, but I’m not sure what the risks of it are. It seems to me that since the generic type parameters are erased at runtime, essentially you’re just bypassing all type checking here.