首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将列表转换为kotlin中的MutableList在JVM运行时失败

将列表转换为kotlin中的MutableList在JVM运行时失败
EN

Stack Overflow用户
提问于 2022-08-30 20:24:49
回答 2查看 79关注 0票数 1
代码语言:javascript
复制
val list = listOf(1, 2, 3)

fun main() {
    if (list is MutableList) {
        list.add(4)
    }
}

上面的代码引发下面的运行时异常。

代码语言:javascript
复制
Exception in thread "main" java.lang.UnsupportedOperationException
 at java.util.AbstractList.add (:-1) 
 at java.util.AbstractList.add (:-1) 
 at FileKt.main (File.kt:5) 

在阅读了Kotlin的收藏文件之后,我了解到kotlin通过接口区分可变集合和不可变集合,并且不变接口没有任何像add()这样的可变方法,但是我想知道在JVM平台上List和MutableList的底层实现是什么?在这种情况下,它看起来像底层的具体类有add()方法,但是它会抛出一个异常。

问题:

由于我在Java方面经验不多,所以很难在JVM中找到List和MutableList接口的具体实现。如果有人向我指出代码或跟踪这些接口下的实际java集合的方法,那就太好了。这两个接口是由相同的java集合还是由不同的java集合实现的?

注:

我这样做是为了学习,我知道这是非常糟糕的代码,我应该使用.toMutableList()扩展函数,而不是智能转换。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-30 20:57:49

正如您所说的,Java并不区分可变列表和不可变列表。kotlin.List (或者至少在类型系统中不区分。) ,因此将java.util.Listkotlin.MutableList类型都映射到java.util.List接口。

这样做的不幸后果是支票:

代码语言:javascript
复制
if (list is MutableList)

…实际上,它只是检查对象是否是java.util.List,所以可变列表和不可变列表都将通过测试。

这就是为什么您的代码要抛出一个UnsupportedOperationException (这是区分不可变列表和任何其他可选特性的一种方法)。

我不知道有什么方法可以可靠地区分可变列表和不可变列表,除非尝试修改它们并查看它们是否抛出异常…

同样值得注意的是,listOf()并不承诺返回任何特定的实现。 所能告诉你的就是它会返回一些实现kotlin.List的东西,但它可能是可变的,也可能是不可变的。 (实际上,我认为这取决于您传递0、1或多个项。 ,但是在未来的Kotlin版本中,确切的实现可能会发生很大变化,所以您不应该做任何假设)。

类似地,mutableListOf()返回kotlin.MutableList的一些实现,但没有承诺哪个实现。

实际上,如果您需要一个可变的列表,那么您应该显式地创建一个列表(或者创建一个特定的类,比如ArrayList,或者更好的方法是调用mutableListOf()并让它选择最合适的类型),如果您不能控制列表的创建,那么--正如您所说--您可以调用toMutableList() (尽管这可能会创建一个不必要的副本)。

票数 2
EN

Stack Overflow用户

发布于 2022-08-30 21:06:44

列表几乎总是可以转换为MutableLists (除非您自己编写了实现Kotlin列表而不是MutableList的类),因为大多数(可能全部?)对于生成列表的Kotlin函数,请在幕后使用Java列表,而Java列表始终等同于Kotlin MutableList。Java使列表不可变的方法是在运行时尝试修改异常时抛出异常,这就是为什么会发生崩溃。

基本上,您不应该将转换为,因为它本质上是不安全的。类将MutableLists的只读视图公开为列表是一种常见的设计模式,以防止它们在外部发生变异。这就是Kotlin在处理不可变异的列表时如何保护您免受崩溃的方法。如果您通过转换来颠覆这种设计模式,有时它将在运行时成功,因为底层列表不是Java不变的列表实现,然后您将触发很难跟踪的bug。

如果您想探索源代码,在IntelliJ IDEA或Android中,您可以通过Ctrl+click函数查看它的源代码。因此,在本例中,您可以使用listOf完成这一操作,并按下命令,直到找到用Java生成的列表实现为止。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73548084

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档