为什么在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
返回true,表示Kotlin不可变集合对象实现了MutableCollection
接口,但是它没有更改集合中的项目,而是抛出了UnsupportedOperationException
是真的吗?如果是,为什么不可变集合对象在Kotlin中实现MutableCollection
接口?
是因为Kotlin集合是从Java集合继承而来的,并且已经存在更改方法(添加,删除,...),并且避免更改集合的唯一方法是重写它并引发异常(即使这是真的) Kotlin不可变集合对象没有必要实现MutableCollection
接口,因为Java更改集合方法已经存在并且可以被覆盖)?
答案 0 :(得分:5)
不,那不是正确的解释。这段代码应该可以帮助您了解发生了什么:
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)
}
输出为
list class is = class java.util.Arrays$ArrayList
is mutable
[42, 2, 3]
因此,解释是listOf(1, 2, 3)
返回Arrays $ ArrayList列表,即通过执行Arrays.asList(1, 2, 3)
在Java中返回的列表。这是一个可变列表,但是您不能添加任何内容,因为它具有固定的大小,因为它由数组支持。
科特林列表并不是真正不变的。它们只是没有任何允许对其进行突变的方法:它们只是不可变的接口,它们仅公开实际可变列表的只读方法。如果您欺骗列表并将其转换为可变列表,那么,如果该列表实际上是Java列表,则转换将成功,但是您不知道您是否真的能够对它们进行突变,就像在Java中一样:一个List可能是一个不能完全变异的emptyList,或者是上面示例中的不可调整大小的列表,或者是一个完全可变的列表,例如ArrayList。