For example, lets say you have two classes:
public class TestA {}
public class TestB extends TestA{}
I have a method that returns a L
This is possible due to type erasure. You will find that
List<TestA> x = new ArrayList<TestA>();
List<TestB> y = new ArrayList<TestB>();
x.getClass().equals(y.getClass()); // true
Internally both lists are of type List<Object>
. For that reason you can't cast one to the other - there is nothing to cast.
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.
List<CharSequence> parent =
Arrays.asList("1","2","3", new StringBuffer("4"));
List<String> strings =
Lists.adapt(parent).selectInstancesOf(String.class);
Assert.assertEquals(Arrays.asList("1","2","3"), strings);
I included StringBuffer
in the example to show that selectInstances
not only downcasts the type, but will also filter if the collection contains mixed types.
Note: I am a committer for Eclipse Collections.
You cannot cast List<TestB>
to List<TestA>
as Steve Kuo mentions BUT you can dump the contents of List<TestA>
into List<TestB>
. Try the following:
List<TestA> result = new List<TestA>();
List<TestB> data = new List<TestB>();
result.addAll(data);
I've not tried this code so there are probably mistakes but the idea is that it should iterate through the data object adding the elements (TestB objects) into the List. I hope that works for you.
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:
class TestA{};
class TestB extends TestA{};
List<? extends TestA> listA;
List<TestB> listB = (List<TestB>) listA;
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:
List<TestA> badlist = null; // Actually contains TestBs, as specified
List<? extends TestA> talist = badlist; // Umm, works
List<TextB> tblist = (List<TestB>)talist; // TADA!
Exactly what you asked for, right? or to be really exact:
List<TestB> tblist = (List<TestB>)(List<? extends TestA>) badlist;
seems to compile just fine for me.
casting of generics is not possible, but if you define the list in another way it is possible to store TestB in it:
List<? extends TestA> myList = new ArrayList<TestA>();
You still have type checking to do when you are using the objects in the list.
Quite strange that manually casting a list is still not provided by some tool box implementing something like:
@SuppressWarnings({ "unchecked", "rawtypes" })
public static <T extends E, E> List<T> cast(List<E> list) {
return (List) list;
}
Of course, this won't check items one by one, but that is precisely what we want to avoid here, if we well know that our implementation only provides the sub-type.