problemas al invocar un método con un argumento de tipo genérico

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 de esta clase extends los Numerable de la interfaz del.

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.

preguntado el 09 de marzo de 12 a las 14:03

lo que es this (what class declaration)? -

whops, sorry. it is an IdnElement. -

2 Respuestas

Say you have classes A y B that both extend Numerable. Then there are three valid types of IdnList: IdnList<A>, IdnList<B>y IdnList<Numerable>.

I hope you would agree that you shouldn't be able to add any Numerable a una IdnList<A>.

Now, in this line of code, how does the compiler know whether you've matched up the types correctly?

(IdnList<?>)this).add((Numerable)childToAdd);

All it knows is that childToAdd es un Numerable, Y que this es una especie de IdnList. 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.

respondido 09 mar '12, 15:03

ok, I get what you're saying. But given I'd prefer not to declare the type of my IdnList (I'm working with reflection and I'd like to stay general) it seems I have no elegant way to solve my problem. - mavvamaldo

The problem lies in the reference to the instance of the IdnList in your other class. I cannot see it in your code example, but it appears that it does not have the proper type associated with it, especially not when it is being cast to a wildcard.

Since the IdnList requires a type (T) set per instance, there is no way for the compiler to know what you are trying to do.

If your reference to your IdnList has the proper type associated with it, it will accept any subclass of T, like so:

  IdnList<Numerable> list = new IdnList<Numerable>();
  list.add(new Numerable());
  list.add(new AnotherType());
  list.add(new YetAnotherType());

(Given that AnotherType and YetAnotherType are subclasses of Numerable)

Since you do not have any type set on the reference to your instance, I am guessing that what you are actually trying to do is this:

public class IdnList extends IdnElement implements List<Numerable> {

    private LinkedList<Numerable> linkedList;

    @Override
    public boolean add(Numerable e) {
        return linkedList.add(e);
    }
}

respondido 09 mar '12, 15:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.