【问题标题】:Kotlin: Modifying (immutable) List through cast, is it legitimate?Kotlin:通过强制转换修改(不可变)列表,合法吗?
【发布时间】:2016-06-21 23:55:33
【问题描述】:

我们知道 Kotlin 中的 List 是不可变的,即你不能像下面这样添加和删除。

class TempClass {
    var myList: List<Int>? = null
    fun doSomething() {
        myList = ArrayList<Int>()
        myList!!.add(10)
        myList!!.remove(10)
    }
}

但如果我们将其转换为如下所示的 ArrayList,则添加和删除可以正常工作。

class TempClass {
    var myList: List<Int>? = null
    fun doSomething() {
        myList = ArrayList<Int>()
        (myList!! as ArrayList).add(10)
        (myList!! as ArrayList).remove(10)
    }
}

我只是觉得这很奇怪,因为 myList 实际上是一个 List,它被认为是不可变的。并投射它,让它被改变。

上面所做的(转换为 Array 并修改内容)是否合法,或者需要改进语言以禁止这样做?

【问题讨论】:

  • 提供的链接确实解释了 List 不是不可变的,而是可读的。但是鉴于此,“可读”实际上并没有那么“有用”,它仍然可以被强制更改。理想情况下,不应将“可读”转换为“可写”
  • 投到MutableList就够了,ArrayList的超类型
  • 看起来您正在尝试在分配后初始化列表。在这种情况下,您可以使用 ArrayList&lt;Int&gt;().apply { add(10) } 或者更好地使用内置的工厂函数,例如 listOf(10)
  • 今天添加到 Klutter 库的阻止将 List 转换为可变(和其他集合类型)蜡的阻止程序阻止了所有相关操作,例如从列表中收到的 Iterator,从列表中收到的 subList列表,来自地图的entrySet 等等。请参阅:stackoverflow.com/a/38002121/3679676 ...您不能围绕它进行投射,也不能对其返回任何其他集合,它们是真正受到保护的。

标签: collections kotlin


【解决方案1】:

有几种不同类型的不变性:

从单独的 SO 答案 here 中提到了一个。

只读 - 您不应该更改它(Kotlin 的列表),但可以更改(转换为 Mutable,或从 Java 更改)。

List 只是一个没有变异方法的接口,但是如果将其转换为MutableList,则可以更改实例。

然后有人继续评论说 Kotlin 选择只读以直接使用 Java 集合,因此使用 Java 集合没有开销或转换。

Kotlin List 是只读的,不是不可变的。其他调用者(例如 Java)可能会更改列表。 Kotlin 调用者可能会转换列表并更改它。没有不可变的保护。

原文来源:Kotlin and Immutable Collections?

【讨论】:

  • 谢谢 gotnull。这解释得很好。 Immutable != Readable...“Readable”不如“Immutable”安全/
  • kotlin 库中 List 的一些实例是不可变的,例如演员表会失败。您必须确保您的列表确实是 ArrayList 的子类
【解决方案2】:

合法吗?嗯,是。在某些用例中这是有意义的。

这是个好主意吗?我认为不是,特别是如果您正在谈论投射某个外部库返回的列表时。如果有人真的给你一些List 实现,而这些实现确实是不可变的并且没有实现MutableList,那么强制转换将失败。目前(Kotlin 1.0.2),Kotlin 的所有 Lists 也是 MutableLists 并不意味着您在代码中看到的每个 List 也是 MutableList

【讨论】:

  • 您的意思是“Kotlin 的列表也是 MutableList”吗?
  • @Ilya 是的,已修复。
【解决方案3】:

现在,如果您使用 listOf(),您将获得一个包含所有方法的列表,这些方法会改变列表,抛出 java.lang.UnsupportedOperationException:

val list = listOf(1, 2)

val mlist = list as MutableList

mlist.add(3)

这会抛出:

Exception in thread "main" java.lang.UnsupportedOperationException
        at java.util.AbstractList.add(AbstractList.java:148)

【讨论】:

    猜你喜欢
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-02
    • 1970-01-01
    相关资源
    最近更新 更多