首页 > 解决方案 > Kotlin:String 类型的 ArrayList:应用程序在通过赋值初始化元素时崩溃

问题描述

基本上,这段代码有效:

var optionsList = ArrayList<String>()
        optionsList.add("Alpha")
        optionsList.add("Bravo")
        optionsList.add("Charlie")
        optionsList[2] = "Foxtrot"// Assignment works (only) if initialization has been done previously through add()

但是,以下情况会使应用程序崩溃(没有编译时错误或警告):

var optionsList = ArrayList<String>(3)
        optionsList[0] = "Alpha"
        optionsList[1] = "Bravo"
        optionsList[2] = "Charlie"

这似乎出乎意料,我无法弄清楚崩溃的原因。在我的理解中,这两种方式应该是等价的——在第一种方式中,我们一次只为一个元素分配内存和初始化,而在第二种方式中,我们在开始时为所有元素分配内存,然后再更改值。

有人可以帮我理解这里可能发生的事情吗?我刚刚开始学习 Kotlin 并且过去使用过 C++,所以这可能会影响我对此的思考方式。

标签: kotlin

解决方案


在 Kotlinlist[n]中是 的简写list.get(n),使用赋值运算符list[n] = value将其翻译为list.set(n, value)

optionsList[2] = "Foxtrot"尝试覆盖 2 处的值并返回 KDocs 中定义的旧值(永远不会为空),所以如果该索引处没有值,它将返回什么?

public E set(int index, E element) {
    Objects.checkIndex(index, size);
    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}

确实,内存中的空间是为

var optionsList = ArrayList<String>(3)

但是由于operator fun set(index: Int, element: E): E需要返回旧值,这是不可能的,因为该索引处的值不存在,所以它无法执行操作。

编辑:分配空间的目的是减少添加大量值所花费的时间,例如,如果您想添加大量值,例如 10000,那么预分配(0.6 毫秒)所需的时间大约减少 3.5 倍比动态分配的 ArrayList (2ms)。见:https ://pl.kotl.in/iV3ZNNjOC


推荐阅读