For example, lets say you have two classes:
public class TestA {}
public class TestB extends TestA{}
I have a method that returns a List<TestA>
and I would like to cast all the objects in that list to TestB
so that I end up with a List<TestB>
.
I think you are casting in the wrong direction though... if the method returns a list of
TestA
objects, then it really isn't safe to cast them toTestB
.Basically you are asking the compiler to let you perform
TestB
operations on a typeTestA
that does not support them.Since this is a widely referenced question, and the current answers mainly explain why it does not work (or propose hacky, dangerous solutions that I would never ever like to see in production code), I think it is appropriate to add another answer, showing the pitfalls, and a possible solution.
The reason why this does not work in general has already been pointed out in other answers: Whether or not the conversion is actually valid depends on the types of the objects that are contained in the original list. When there are objects in the list whose type is not of type
TestB
, but of a different subclass ofTestA
, then the cast is not valid.Of course, the casts may be valid. You sometimes have information about the types that is not available for the compiler. In these cases, it is possible to cast the lists, but in general, it is not recommended:
One could either...
The implications of the first approach (which corresponds to the currently accepted answer) are subtle. It might seem to work properly at the first glance. But if there are wrong types in the input list, then a
ClassCastException
will be thrown, maybe at a completely different location in the code, and it may be hard to debug this and to find out where the wrong element slipped into the list. The worst problem is that someone might even add the invalid elements after the list has been casted, making debugging even more difficult.The problem of debugging these spurious
ClassCastExceptions
can be alleviated with theCollections#checkedCollection
family of methods.Filtering the list based on the type
A more type-safe way of converting from a
List<Supertype>
to aList<Subtype>
is to actually filter the list, and create a new list that contains only elements that have certain type. There are some degrees of freedom for the implementation of such a method (e.g. regarding the treatment ofnull
entries), but one possible implementation may look like this:This method can be used in order to filter arbitrary lists (not only with a given Subtype-Supertype relationship regarding the type parameters), as in this example:
This is possible due to type erasure. You will find that
Internally both lists are of type
List<Object>
. For that reason you can't cast one to the other - there is nothing to cast.The problem is that your method does NOT return a list of TestA if it contains a TestB, so what if it was correctly typed? Then this cast:
works about as well as you could hope for (Eclipse warns you of an unchecked cast which is exactly what you are doing, so meh). So can you use this to solve your problem? Actually you can because of this:
Exactly what you asked for, right? or to be really exact:
seems to compile just fine for me.
When you cast an object reference you are just casting the type of the reference, not the type of the object. casting won't change the actual type of the object.
Java doesn't have implicit rules for converting Object types. (Unlike primitives)
Instead you need to provide how to convert one type to another and call it manually.
This is more verbose than in a language with direct support, but it works and you shouldn't need to do this very often.
You can use the
selectInstances
method in Eclipse Collections. This will involved creating a new collection however so will not be as efficient as the accepted solution which uses casting.I included
StringBuffer
in the example to show thatselectInstances
not only downcasts the type, but will also filter if the collection contains mixed types.Note: I am a committer for Eclipse Collections.