Search code examples
javagenericscollectionswildcard

upcast from List<subclass> to List<superclass> via List<?>


I have a class A and a class B extends A

In another class C I have a field

private List<B> listB;

Now, for some unusual reason, I have to implement this method in C

public List<A> getList();

I tried to do so by forcing an upcast of listB field to List<A> via a List<?> cast:

public List<A> getList(){
    return (List<A>)(List<?>)listB;
}

Clients should do

List<A> list = getList();
for(A a:list){
    //do something with a
}

I did some test and it seems work correctly, but honestly I am not sure of the all possible implications.

Is this solution correct? And Is it the best solution?

Thanks for your answers.


Solution

  • No, this isn't generally type-safe. The client shouldn't be able to do

    List<A> list = getList();
    

    because otherwise they could write

    list.add(new C()); // Where C extends A
    

    Then the original code which knows about the list as a List<B> will have problems when it tries to use it, assuming that every element is compatible with B.

    You could either wrap the original list to make it read-only, effectively - or make getList return a List<? extends A>, which means that clients won't be able to add items to it anyway.

    If the list implementation you're using is unmodifiable, then it won't actually cause problems - but I'd still personally avoid it where possible.