Kotlin中数组两种遍历赋值为何一个编译通过,一个报Val cannot be reassigned?
为什么一个Kotlin数组修改函数能编译,另一个报“Val cannot be reassigned”?
咱们先把两个函数摆出来对比着看:
可正常编译的函数
fun <T> Array<T>.mapInPlace2(transform: (T) -> T) { for (i in this.indices) { this[i] = transform(this[i]) } }
报错的函数(提示Val cannot be reassigned)
fun <T> Array<T>.mapInPlace1(transform: (T) -> T) { for (i in this) { i = transform(i); } }
核心差异与原因解析
这两个函数的本质区别,在于你操作的是数组的「元素位置」,还是「元素的局部副本」:
mapInPlace2能正常工作的原因
这里用for (i in this.indices)遍历的是数组的索引,然后通过this[i]访问数组里的元素存储位置。Kotlin的Array<T>是可变容器,允许通过索引直接修改对应位置的元素值——你做的是「把转换后的值放到数组的第i个位置上」,完全符合数组的设计规则,所以编译没问题,而且确实能修改原数组的元素。mapInPlace1报错的原因
这里的for (i in this)是遍历数组的元素本身,但要注意:遍历出来的i是原元素的一个局部只读副本(相当于隐式声明了val i: T)。你试图i = transform(i),本质是想给一个不可变的val变量重新赋值,这直接违反了Kotlin的变量不可变规则,所以编译器会抛出Val cannot be reassigned的错误。
退一步说,就算允许赋值,你修改的也只是局部变量i,和原数组里的元素没有任何关联,根本达不到「原地修改数组」的目的。
总结
- 如果要修改数组的元素,必须通过索引定位元素位置来赋值,直接操作数组容器本身的存储位置。
- 直接遍历元素得到的是局部副本,既不能修改(因为是
val),修改了也不会影响原数组。
内容的提问来源于stack exchange,提问作者Dishonered
相关产品推荐
相关产品推荐

