listOf() 返回可修改的列表。

11
在 Kotlin 中,使用 listOf() 函数创建的列表(应该是不可变的)可以使用 is 运算符通过类型检查来检查是否为 MutableList

示例:

fun main(args: Array<String>) {
    val list = listOf("I'm immutable")

    println(list is MutableList)
}

将打印

true

有趣的是,使用 listOf<String>() 创建的空列表将失败并打印false,因为它返回单例对象 EmptyList

经过一番挖掘,发现 mutableListOf() 创建了一个 java.util.ArrayList,而 listOf() 最终创建了一个 java.util.Arrays$ArrayList,但是涉及的所有类都没有实现 MutableList,那么为什么非空列表仍然可以通过类型检查?因此,有没有一种可靠的方法来检查列表是否可变,而无需对其实际实现进行检查(例如 is ArrayList 等)?


1
java.util.Arrays$ArrayList实际上是可变的,因为您可以替换元素。它只是大小固定,因此您无法添加或删除元素。我认为Kotlin必须有一些内部映射或方法来查找Java列表是否具有“可变”属性。Java中不存在MutableList接口,这必须是Kotlin特有的。 - Madjosz
2
listOf 返回一个 SingletonList。为什么 is 在这里返回 true 是一个好问题。 - Zoe stands with Ukraine
2
此外,list::class.java == MutableList::class.java 的输出结果为 false。这两个类并不相同,因此我猜测 is 运算符或其编译的某些代码存在错误。看起来 is 运算符使用 TypeIntrinsics.isMutableList(list); 来检查类型。 - Zoe stands with Ukraine
1
它仍在JVM上运行,在那里实际上首先没有MutableListList之间的运行时区别。只有在编译时才有区别。 - Louis Wasserman
1
从查看源代码(https://github.com/JetBrains/kotlin/blob/1.2.70/libraries/stdlib/jvm/src/kotlin/collections/CollectionsJVM.kt#L18)来看,我认为singletonList()只是返回一个不可变列表的函数,但我的调试器显示,当只有一个参数时,列表的类型是Collections$SingletonList,所以你是正确的。当有两个或更多参数时,会创建一个Arrays$ArrayList,不过我也不知道它们之间的实际区别。 - Joel Evans
显示剩余3条评论
1个回答

9
< p > ListMutableList 之间的分离是 Kotlin 编译器创建的一个幻觉。在运行时,Kotlin 使用 Java 集合类,这些类只有一个包含读和写方法的 List 接口。编译时对 ListMutableList 的引用都被编译为 java.util.List 引用。因此,在运行时无法检测列表是否为 MutableList


谢谢您的回答。MutableList不可以直接从java.util.List继承(在编译时),这两者之间需要保持区分吗? - Joel Evans
2
不行,因为Kotlin使用Java集合作为实现类,而不仅仅是接口定义,而且java.util.ArrayList没有实现任何Kotlin接口。 - yole
1
这实际上在他们的文档中已经说明了:https://kotlinlang.org/docs/reference/collections.html - “目前,listOf方法是使用数组列表实现的,但将来可能会返回更多内存高效的完全不可变集合类型,利用它们知道自己不能改变的事实。” - Mauker
需要澄清一下。List的Kdoc没有将其描述为不可变的,只是它仅公开“只读”方法。除非返回它的函数在Kdoc中指定它是不可变的,否则永远不应该期望List是不可变的。一个常见的设计模式是一个类持有一个私有的MutableList,但将同一个实例作为只读List公开。在这种情况下,用户不能期望List是不可变的,就像他们不能假设访问val属性总是返回相同的值(val表示只读,而不是常量)。 - Tenfour04
因此,可以检测List是否为MutableList。但是这样做并没有什么实际用处。使用单个参数的listOf()确实返回一个不是MutableList的List,并且它的Kdoc反映了这一事实。listOf()函数的某些重载不声明返回不可变List,只声明返回只读List。 - Tenfour04

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接