(可变集合是可变的)在Kotlin中返回true

时间:2018-12-27 21:58:32

标签: kotlin immutable-collections

为什么在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更改集合方法已经存在并且可以被覆盖)?

1 个答案:

答案 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。