I recently study about kotlin Generics, But i found some weird stituation
interface MyItem
fun <ITEM : MyItem> bindItem(items: List<ITEM>?) {
val castedItem = items as List<MyItem>?
}
fun <ITEM : MyItem> bindItem2(items: MutableList<ITEM>?) {
val castedItem = items as MutableList<MyItem>?
}
Only In MutableList case compiler warn about unchecked Cast
If anyone knows about this situation, Please tell me about this.
The
List
interface has declaration site covariance (<out T>
). This means it is safe to "upcast" the type because a List only ever outputs items. For example, if you have aList<Int>
, it is safe to use it as aList<Number>
because anInt
can always be safely cast to aNumber
. When you retrieve items from the list, they always satisfy being the typeInt
or the supertypeNumber
.MutableList
does not have a covariant type. It is invariant at the declaration site. This means it is not inherently safe to "upcast" its type. For example, if you cast yourMutableList<Int>
to aMutableList<Number>
, it is not safe to use theMutableList<Number>
reference, because it would let you add aFloat
to the list. When the original reference is used as aMutableList<Int>
and tries to retrieve a value from it, it will get a ClassCastException for trying to use theFloat
as anInt
.In this case, you could safely cast the
MutableList
to a covariant type, like this:but a
MutableList
with a covariant type is not really any different than aList
(except that you canclear()
it), so it would be better to cast it to aList<MyItem>
to make the intent clearer.