Java Generics are a bundle of compromises and workarounds. Backwards compatibility is a PITA. We all know that. Anyway...
I had a service class that, due to some refactoring, was now going to be returning a List<ParentClass> whereas before it could return a List<ChildClass>. We had some A/B testing inside the implementation, so in some cases, we would be actually returning a List<ChildClassTwo> from our DAO class.
My original fix for this was to create a new ArrayList and initialise it with the List of ChildClass or ChildClassTwo, but I didn't like the idea of having to create a new object just to change types.
But there's actually a better way, one that does not involve creating an extra wrapper object, that I found on StackOverflow.
To use the classic O-O hierarchy of Animal and Dog classes:
List<Dog> dogsInLocation = dao.findDogs(location);
List <Animal> animalsInLocation = (List<Animal>) (List) dogsInLocation;
So basically you are casting the List<Dog> "up" to a List, and then casting it "down" to a List<Animal>
Trying to do
(List<Animal>) dogsInLocation;
gives you an "Inconvertible types" error. You can't directly go from a typed list of one type to a type of another.
The workaround is to use type erasure, turn it into a standard List, which gets rid of the type information about List<Dogs>, and *then* cast it to a List<Animal>