How do you cast a List of supertypes to a List of subtypes?
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;
Casting a list of an object to a list of super types
Java Generics are invariant. This means that, given two concrete classes, A
and B
, SomeClass<A>
has no relationship to SomeClass<B>
, even if B
is a subtype of A
.
So, List<RangeData>
is not a supertype of List<IncomeRanges>
. Instead, you should use an upper bounded wildcard, like this:
public RangeData findRangeData(List<? extends RangeData> list, int value) {
....code....
}
For more information, you can check the documentation on Generics, Inheritance, and Subtypes.
Most efficient way to cast List SubClass to List BaseClass
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.
Java-8 stream - cast list of sub types to list of super types
You can collect the items into lists of the more general type by specifying the type parameter to use for toList
:
Collectors.<ScheduleContainer>toList()
Adding list of subtypes to list of supertypes in Kotlin
The problem is that imageList
may only contain instances of type Image
. However, attachableList
contains instances of type Attachable
. Since other classes than Image
may implement Attachable
, you cannot safely add all elements from attachableList
to imageList
.
If you're sure that attachableList
only contains instances of type Image
, using it as Image
is fine (though there's also .filterIsInstance<Image>()
. I don't see a way around this using the variance features.
Converting a collection of subtype to collection of supertype
Easiest way, assuming you don't need to modify the collection through as1
:
Collection<A> as1 = Collections.unmodifiableCollection(bs);
If you do need to modify the collection, the only safe thing to do is to copy it:
Collection<A> as1 = new ArrayList<>(bs);
Dart - Casting List SuperType to List SubType using generics
In Dart (and indeed in many languages) generics screws with the concept of inheritance. You would think that if Bar
inherits from Foo
, that List<Bar>
would also be castable to List<Foo>
.
This is not actually going to be the case because of how generics work. When you have a generic class, every time you use that class with a different type, that type is treated as a completely separate class. This is because when the compiler compiles those types, class MyGenericType<Foo> extends BaseClass
and class MyGenericType<Bar> extends BaseClass
are basically converted to something like class MyGenericType_Foo extends BaseClass
and class MyGenericType_Bar extends BaseClass
.
Do you see the problem? MyGenericType_Foo
and MyGenericType_Bar
are not descendants of one another. They are siblings of each other, both extending from BaseClass
. This is why when you try to convert a List<Entity>
to List<Vehicle>
, the cast doesn't work because they are sibling types, not a supertype and subtype.
With all this being said, while you cannot directly cast one generic type to another based on the relationship of the generic type parameter, in the case of List
there is a way to convert one List
type to another: the cast
method.
List<Entity> entityList = <Entity>[...];
List<Vehicle> vehicleList = entityList.cast<Vehicle>(); // This cast will work
One thing to note though, if you are casting from a supertype generic to a sub-type generic and not all the elements of the list are that new type, this cast will throw an error.
Convert List Object to List CustomClass
If you know in advance that all of your objects are actually CustomClass
objects, you can perform an unsafe cast:
@SuppressWarnings("unchecked")
List<CustomClass> list = (List<CustomClass>)(List<?>)getObjects();
This is the fastest solution; practically in runtime nothing is performed except the variable assignment. However if you're wrong and your list actually contains other objects, you may have an unexpected ClassCastException
later.
Java 8 stream - cast list items to type of subclass
It's possible, but you should first consider if you need casting at all or just the function should operate on subclass type from the very beginning.
Downcasting requires special care and you should first check if given object can be casted down by:
object instanceof ScheduleIntervalContainer
Then you can cast it nicely by:
use functional method to cast like
ScheduleIntervalContainer.class::cast
So, the whole flow should look like:
collection.stream()
.filter(obj -> obj instanceof ScheduleIntervalContainer)
.map(ScheduleIntervalContainer.class::cast)
// other operations
Related Topics
How to Implement Basic Authentication with Glassfish
Jfilechooser and Browsing Networked MAChines
How to Build Netty-Transport-Native-Epoll-4.0.32.Final-Linux-X86_64.Jar
Command Working in Terminal, But "No Closing Quote" Error When Used Process.Exec
Issues with Corba Communication
No Swt-Mozilla-Gtk-4332 in Java.Library.Path
One to One Mapping of Java Thread to Linux Thread (Lwp)
Swt Expandlistener Executes Before Collapse Occurs on Linux
Java File Locking Mechanism for File Based Process Communication
Commportidentifier.Getportidentifiers with Zero Ports on Linux
Runtime Exception Not Terminating the Programm
Load Native Libraries in an Eclipse Rcp Application on Linux
Execute Source Command from Java
Execute Bash Command Within Java Program
Set Environment Variable in Shell Script/Access in Java Program