For example, lets say you have two classes:
public class TestA {}
public class TestB extends TestA{}
I have a method that returns a L
With Java 8, you actually can
List<TestB> variable = collectionOfListA
.stream()
.map(e -> (TestB) e)
.collect(Collectors.toList());
Simply casting to List<TestB>
almost works; but it doesn't work because you can't cast a generic type of one parameter to another. However, you can cast through an intermediate wildcard type and it will be allowed (since you can cast to and from wildcard types, just with an unchecked warning):
List<TestB> variable = (List<TestB>)(List<?>) collectionOfListA;
This should would work
List<TestA> testAList = new ArrayList<>();
List<TestB> testBList = new ArrayList<>()
testAList.addAll(new ArrayList<>(testBList));
You really can't*:
Example is taken from this Java tutorial
Assume there are two types A
and B
such that B extends A
.
Then the following code is correct:
B b = new B();
A a = b;
The previous code is valid because B
is a subclass of A
.
Now, what happens with List<A>
and List<B>
?
It turns out that List<B>
is not a subclass of List<A>
therefore we cannot write
List<B> b = new ArrayList<>();
List<A> a = b; // error, List<B> is not of type List<A>
Furthermore, we can't even write
List<B> b = new ArrayList<>();
List<A> a = (List<A>)b; // error, List<B> is not of type List<A>
*: To make the casting possible we need a common parent for both List<A>
and List<B>
: List<?>
for example. The following is valid:
List<B> b = new ArrayList<>();
List<?> t = (List<B>)b;
List<A> a = (List<A>)t;
You will, however, get a warning. You can suppress it by adding @SuppressWarnings("unchecked")
to your method.
if you have an object of the class TestA
, you can't cast it to TestB
. every TestB
is a TestA
, but not the other way.
in the following code:
TestA a = new TestA();
TestB b = (TestB) a;
the second line would throw a ClassCastException
.
you can only cast a TestA
reference if the object itself is TestB
. for example:
TestA a = new TestB();
TestB b = (TestB) a;
so, you may not always cast a list of TestA
to a list of TestB
.
class MyClass {
String field;
MyClass(String field) {
this.field = field;
}
}
@Test
public void testTypeCast() {
List<Object> objectList = Arrays.asList(new MyClass("1"), new MyClass("2"));
Class<MyClass> clazz = MyClass.class;
List<MyClass> myClassList = objectList.stream()
.map(clazz::cast)
.collect(Collectors.toList());
assertEquals(objectList.size(), myClassList.size());
assertEquals(objectList, myClassList);
}
This test shows how to cast List<Object>
to List<MyClass>
. But you need to take an attention to that objectList
must contain instances of the same type as MyClass
. And this example can be considered when List<T>
is used. For this purpose get field Class<T> clazz
in constructor and use it instead of MyClass.class
.