You can try to convert the super class variable to the sub class type by simply using the cast operator. But, first of all you need to create the super class reference using the sub class object and then, convert this (super) reference type to sub class type using the cast operator.
As it was said before, you can't cast from superclass to subclass unless your object was instantiated from the subclass in the first place.
Try the following: List<TestA> result = new List<TestA>(); List<TestB> data = new List<TestB>(); result. addAll(data);
you can always cast any object to any type by up-casting it to Object first. in your case: (List<Customer>)(Object)list; you must be sure that at runtime the list contains nothing but Customer objects.
The syntax for this sort of assignment uses a wildcard:
List<SubClass> subs = ...;
List<? extends BaseClass> bases = subs;
It's important to realize that a List<SubClass>
is not interchangeable with a List<BaseClass>
. Code that retains a reference to the List<SubClass>
will expect every item in the list to be a SubClass
. If another part of code referred to the list as a List<BaseClass>
, the compiler will not complain when a BaseClass
or AnotherSubClass
is inserted. But this will cause a ClassCastException
for the first piece of code, which assumes that everything in the list is a SubClass
.
Generic collections do not behave the same as arrays in Java. Arrays are covariant; that is, it is allowed to do this:
SubClass[] subs = ...;
BaseClass[] bases = subs;
This is allowed, because the array "knows" the type of its elements. If someone attempts to store something that isn't an instance of SubClass
in the array (via the bases
reference), a runtime exception will be thrown.
Generic collections do not "know" their component type; this information is "erased" at compile time. Therefore, they can't raise a runtime exception when an invalid store occurs. Instead, a ClassCastException
will be raised at some far distant, hard-to-associate point in code when a value is read from the collection. If you heed compiler warnings about type safety, you will avoid these type errors at runtime.
erickson already explained why you can't do this, but here some solutions:
If you only want to take elements out of your base list, in principle your receiving method should be declared as taking a List<? extends BaseClass>
.
But if it isn't and you can't change it, you can wrap the list with Collections.unmodifiableList(...)
, which allows returning a List of a supertype of the argument's parameter. (It avoids the typesafety problem by throwing UnsupportedOperationException on insertion tries.)
As @erickson explained, if you really want a reference to the original list, make sure no code inserts anything to that list if you ever want to use it again under its original declaration. The simplest way to get it is to just cast it to a plain old ungeneric list:
List<BaseClass> baseList = (List)new ArrayList<SubClass>();
I would not recommend this if you don't know what happens to the List and would suggest you change whatever code needs the List to accept the List you have.
I missed the answer where you just cast the original list, using a double cast. So here it is for completeness:
List<BaseClass> baseList = (List<BaseClass>)(List<?>)subList;
Nothing is copied, and the operation is fast. However, you are tricking the compiler here so you must make absolutely sure to not modify the list in such a way that the subList
starts containing items of a different sub type. When dealing with immutable lists this is usually not an issue.
Below is a useful snippet that works. It constructs a new array list but JVM object creation over head is in-significant.
I saw other answers are un-necessarily complicated.
List<BaseClass> baselist = new ArrayList<>(sublist);
List<BaseClass> convertedList = Collections.checkedList(listOfSubClass, BaseClass.class)
What you are trying to do is very useful and I find that I need to do it very often in code that I write. An example use case:
Say we have an interface Foo
and we have a zorking
package which has a ZorkingFooManager
which creates and manages instances of package-private ZorkingFoo implements Foo
. (A very common scenario.)
So, ZorkingFooManager
needs to contain a private Collection<ZorkingFoo> zorkingFoos
but it needs to expose a public Collection<Foo> getAllFoos()
.
Most java programmers would not think twice before implementing getAllFoos()
as allocating a new ArrayList<Foo>
, populating it with all the elements from zorkingFoos
and returning it. I enjoy entertaining the thought that about 30% of all clock cycles consumed by java code running on millions of machines all over the planet is doing nothing but creating such useless copies of ArrayLists which are garbage-collected microseconds after their creation.
The solution to this problem is, of course, down-casting the collection. Here is the best way to do it:
static <T,U extends T> List<T> downCastList( List<U> list )
{
return castList( list );
}
Which brings us to the castList()
function:
static <T,E> List<T> castList( List<E> list )
{
@SuppressWarnings( "unchecked" )
List<T> result = (List<T>)list;
return result;
}
The intermediate result
variable is necessary due to a perversion of the java language:
return (List<T>)list;
produces an "unchecked cast" exception; so far so good; but then:
@SuppressWarnings( "unchecked" ) return (List<T>)list;
is an illegal use of the suppress-warnings annotation.
So, even though it is not kosher to use @SuppressWarnings
on a return
statement, it is apparently fine to use it on an assignment, so the extra "result" variable solves this problem. (It should be optimized away either by the compiler or by the JIT anyway.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With