Kotlin - Val 无法重新分配,但可以通过从索引访问来重新分配?

Kotlin - Val cannot be reassigned , but can be reassigned by accessing from index?

我有这两个函数,我正在尝试修改元素。其中一个编译,另一个说 '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);
}
}

您混淆了对对象和对象本身的引用的可变性。

在第一个示例中,结构是可变的,但对它的引用是不可变的。您可以更改对象本身的结构,但不能更改引用指向的结构。

在第二个示例中,您试图更改对对象的不可变引用,而不是对象本身。

如果你写

val i = obj

obj 如果它是一个可变对象,它仍然可以被改变。 i 无法重新分配,因为引用无法更改。

类似,for 循环中使用的变量也是如此。本质上,写下来...

for (i in array) {
    ...
}

... 等同于 Java:

for (final int i : array) {
    ...
}

这有助于捕获一些常见错误,在这种情况下 - 如果编译器允许 - 您将重新分配这个只包含对真实元素的引用的局部变量,而不更改数组。在 Java 术语中,你会这样做:

for (int i : array) {
    i = transform(i);
}

这个i的新值没有被使用,它不会改变数组本身,当循环到来时它会立即被下一个元素的值覆盖。

试试这个:

for(i:Int in 0 until this.size) {
    this[i] = "your value"
}