The code is also at https://github.com/timp21337/java-generics-example
package a;
import java.util.List;
public interface Container<T> {
List<T> getThings();
}
public class ContainerContainer {
public Container<Thing> getThingContainer() {
return new ThingContainer<Thing>();
}
}
public class ThingContainer<T extends a.Thing> implements Container<T> {
@Override
public List<T> getThings() {
return null;
}
}
public class Thing {
}
Package b
package b;
import java.util.List;
public class ContainerContainer extends a.ContainerContainer {
ThingContainer<Thing> thingContainer = new ThingContainer<Thing>();
@SuppressWarnings("unchecked")
public a.Container<a.Thing> getContainer() {
return (a.Container<a.Thing>)(Object)thingContainer; //YUCK
}
}
public class ThingContainer<T extends a.Thing>
implements a.Container<T> {
@Override
public List<T> getThings() {
return null;
}
}
public class Thing extends a.Thing {
}
My question is why do I have to coerce the b.ThingContainer (marked YUCK above) when it is a subclass of a.ThingContainer and the Things it contains are subclasses of a.Thing?
Let’s consider a much simpler example, to remove all the irrelevant details. (Here, instead of
b.Thingwe will useString, and instead ofa.Thingwe will useObject;Stringis a subclass ofObject, so it is analogous. Instead ofa.Container, we will useList. The subclassing of the container is irrelevant, as you will see.) If you can understand why this example doesn’t work, you will understand your problem.