In java one can cast instance of a class B into an instance of class A provided that B extends A.
Can this be done also for type-parametrized classes? For instance, for B extending A, I’d like to do the following:
List<A> l = new ArrayList<B>();
I think this should be legal, but the compiler doesn’t agree with me on this point, so I tricked it with the following hack:
List<A> l = (List<A>)(List) new ArrayList<B>();
…but I think that I’ll be hit by a velociraptor. Is there an elegant way of doing this?
Generally, when humans and compilers disagree, it is safe to take the compiler’s side. Instead of tricking the compiler, you should first understand why it does not allow the conversion.
Consider this: you make a
List<B>, like this:Everyone is happy so far. Now let’s do what you think is correct:
At this point, we have
listAthat is entirely ours! Let’s play with it: let’s say we have another classCextendingA. Can we do this?But wait, do you see what we have done? Our
listBcontains aCnow! This is why the compiler does not allow the conversion; this is also why your code is not safe in cases when you attempt to add anything to the list.To work around this issue, you can use wildcards:
List<? extends A>. However, this will limit your lists to read-only access. If you must allow writing (and you know that you are going to set only the right stuff) use the non-genericListinstead.