You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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); 
    } 
}

核心差异与原因解析

这两个函数的本质区别,在于你操作的是数组的「元素位置」,还是「元素的局部副本」:

  1. mapInPlace2能正常工作的原因
    这里用for (i in this.indices)遍历的是数组的索引,然后通过this[i]访问数组里的元素存储位置。Kotlin的Array<T>是可变容器,允许通过索引直接修改对应位置的元素值——你做的是「把转换后的值放到数组的第i个位置上」,完全符合数组的设计规则,所以编译没问题,而且确实能修改原数组的元素。

  2. mapInPlace1报错的原因
    这里的for (i in this)是遍历数组的元素本身,但要注意:遍历出来的i是原元素的一个局部只读副本(相当于隐式声明了val i: T)。你试图i = transform(i),本质是想给一个不可变的val变量重新赋值,这直接违反了Kotlin的变量不可变规则,所以编译器会抛出Val cannot be reassigned的错误。
    退一步说,就算允许赋值,你修改的也只是局部变量i,和原数组里的元素没有任何关联,根本达不到「原地修改数组」的目的。

总结

  • 如果要修改数组的元素,必须通过索引定位元素位置来赋值,直接操作数组容器本身的存储位置。
  • 直接遍历元素得到的是局部副本,既不能修改(因为是val),修改了也不会影响原数组。

内容的提问来源于stack exchange,提问作者Dishonered

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:24:08