在 Kotlin 中将 ArrayList 转换为 List 时的不变性问题

Immutability issue when casting ArrayList to List in Kotlin

我试图深入了解Kotlin中的集合。这样做时我未能保持 List 的可变性:

  val intsA = arrayListOf(1, 2, 3)
  val intsB: List<Int> = intsA
  intsA.add(4)
  println("intsA = $intsA && intsB = $intsB")

结果:

intsA = [1, 2, 3, 4] && intsB = [1, 2, 3, 4]

是的,我知道我正在传递参考,我可以通过以下方式更安全地做到这一点:

val intsB: List<Int> = intsA.toList()

我还是不太明白幕后发生了什么?为什么 Kotlin 中的默认转换不能更安全地完成?因为将那段代码放在代码中的某处并在以后使用它时认为它是不可变的,就像这里一样:

fun main(args: Array<String>) {

    val intsA = arrayListOf(1)
    val intsB: List<Int> = intsA
    val myClass = MyClass(intsB)

    intsA.add(2)
    println("intsA = $intsA && intsB = $intsB && myClass = $myClass")

}

class MyClass(val list: List<Int>){
    override fun toString(): String {
        return "MyClass(list=$list)"
    }
}

结果:

intsA = [1, 2] && intsB = [1, 2] && myClass = MyClass(list=[1, 2])

.toList() 调用并不是启用此 "immutabilty" 的一些高级演员表。该函数只是在内部构造一个全新的 List ,并将元素从原始列表复制到新列表中。这就是为什么对原始列表的修改不再影响新列表。


至于为什么可以引用同一个列表作为 ListMutableList - 这确实是 OOP 的一个基本特征。您可以通过不同的接口为不同的客户端公开相同的对象,并对其进行不同的操作。

A​​ val 并不意味着列表是不可变的。这只是意味着引用不能更改。您提供的代码没有不变性。您可能想要做的是使用 listOf(它创建一个不可变的列表)而不是 arrayListOf,它创建一个 ArrayList 的实例,它是可变的。

顺便说一句,Kotlin 本身还不提供对 immutable collections 的支持,但这可能有一天会实现。