3

I recently study about kotlin Generics, But i found some weird stituation

IDE image

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.

1 Answer 1

12

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 a List<Int>, it is safe to use it as a List<Number> because an Int can always be safely cast to a Number. When you retrieve items from the list, they always satisfy being the type Int or the supertype Number.

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 your MutableList<Int> to a MutableList<Number>, it is not safe to use the MutableList<Number> reference, because it would let you add a Float to the list. When the original reference is used as a MutableList<Int> and tries to retrieve a value from it, it will get a ClassCastException for trying to use the Float as an Int.

In this case, you could safely cast the MutableList to a covariant type, like this:

val castedItem = items as MutableList<out MyItem>?

but a MutableList with a covariant type is not really any different than a List (except that you can clear() it), so it would be better to cast it to a List<MyItem> to make the intent clearer.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.