问题
Why this is happening in Kotlin:
val list: List<Int> = listOf(1, 2, 3)// Immutable list
if(list is MutableCollection<*>){// why this "if" condition is true?
println("is mutable")// this line is printed
(list as MutableCollection<Int>).add(4) // this results to java.lang.UnsupportedOperationException
}
list is MutableCollection
returns true that shows Kotlin Immutable collection objects implements MutableCollection
interface but instead of changing items in collection it throws UnsupportedOperationException
Is it true? and if yes why Immutable collection objects implement MutableCollection
interface in Kotlin?
Is it because of Kotlin collections inherit from Java Collections and altering methods (add, remove, ...) already is there and the only way to avoid altering collection is to override it and throw an exception (even if this is true it is not necessary for Kotlin immutable collection objects to implement MutableCollection
interface because java altering collection methods already are there and can be overridden)?
回答1:
No, that's not the correct explanation. This code should help you understand what's going on:
val list: List<Int> = listOf(1, 2, 3)
println("list class is = ${list::class.java}")
if(list is MutableCollection<*>) {
println("is mutable")
(list as MutableList<Int>)[0] = 42
println(list)
}
The output is
list class is = class java.util.Arrays$ArrayList
is mutable
[42, 2, 3]
So, the explanation is that listOf(1, 2, 3)
returns an Arrays$ArrayList list, i.e. the list that would be returned in Java by doing Arrays.asList(1, 2, 3)
. It is a mutable list, but you can't add anything to it, because it has a fixed size, since it's backed by an array.
Kotlin lists aren't truly immutable. They just don't have any method allowing to mutate them: they're just immutable interfaces that only expose the readonly methods of an actually mutable list. If you cheat and cast the list to a mutable list, then, if the list is in fact a Java List, the cast will succeed, but you can't know if you're actually be able to mutate them, just like in Java: a List could be an emptyList, which can't be mutated at all, or a non-resizable list as in the above example, or a fully mutable list like an ArrayList.
来源:https://stackoverflow.com/questions/53951277/imutable-collection-is-mutable-returns-true-in-kotlin