字符串类型为:App的Kotlin:ArrayList在通过赋值初始化元素时崩溃
基本上,该代码可以工作:字符串类型为:App的Kotlin:ArrayList在通过赋值初始化元素时崩溃,kotlin,Kotlin,基本上,该代码可以工作: var optionsList = ArrayList<String>() optionsList.add("Alpha") optionsList.add("Bravo") optionsList.add("Charlie") optionsList[2] = "Foxtrot"// Assignment works (only) if initialization has been done
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()
选项列表。添加(“Alpha”)
选项列表。添加(“Bravo”)
选项列表。添加(“查理”)
optionsList[2]=“Foxtrot”//如果之前已通过add()完成初始化,则分配(仅)有效
但是,以下情况会导致应用程序崩溃(没有编译时错误或警告):
var optionsList=ArrayList(3)
选项列表[0]=“Alpha”
选项列表[1]=“好极了”
选项列表[2]=“Charlie”
这似乎出乎意料,我想不出坠机的原因。在我的理解中,这两种方法应该是等效的——在第一种方法中,我们一次只为一个元素分配内存并初始化一个元素,而在第二种方法中,我们在开始和以后更改值时一起为所有元素分配内存
有人能帮我理解引擎盖下面可能发生的事情吗?我刚刚开始学习Kotlin,并使用了C++,这可能会影响我对这个问题的看法。 < P> > Kotlin >代码>列表[n] < /Cord>是
optionsList[2]=“Foxtrot”
尝试覆盖2处的值,并返回中定义的旧值(该值从不为null),因此如果该索引处没有值,它将返回什么
public E集(int索引,E元素){
对象。检查索引(索引、大小);
E oldValue=元素数据(索引);
elementData[索引]=元素;
返回旧值;
}
确实,内存中为中的值分配了空间
var optionsList=ArrayList(3)
但是由于运算符fun set(index:Int,element:E):E
需要返回旧值,这是不可能的,因为该索引处的值不存在,因此它无法执行该操作
编辑:分配空间的目的是减少添加大量值所需的时间,例如,如果您想添加大量值(如10000),则预分配(0.6ms)所需的时间比动态分配的ArrayList(2ms)少约3.5倍。请参阅:
set()
(重载运算符for[n]=
)只能用于替换值,而不能添加新值。如果指定索引中没有元素,它会抛出IndexOutOfBoundException。非常感谢您的回答@AnimeshSahu。问题是,在这种情况下,我很难理解在声明时将ArrayList的大小设置为3有什么意义。这不应该分配空间,从而避免IndexOutOfBoundException吗?换句话说,大小声明有什么区别?@AnimeshSahu您的评论看起来更像是一个答案,介意将其更改为答案吗?首先分配大小可以防止它必须调整支持数组的大小,直到它超出给定的容量。每次它达到其容量时,它必须在引擎盖下分配一个新的、更大的备份阵列,并将所有值复制到它。非常感谢您提供的详细答案。这使我对正在发生的事情有了一个相当好的了解。因此,如果我理解正确,这意味着在给定(以前未使用)索引处初始化ArrayList中元素的唯一方法是顺序使用add()函数,在此之前,set()函数或[]运算符不能用于任何索引。这是正确的理解吗?
var optionsList = ArrayList<String>(3)
optionsList[0] = "Alpha"
optionsList[1] = "Bravo"
optionsList[2] = "Charlie"