I have a Java/Kotlin interop problem. A Kotlin immutable list is compiled into a normal java.util.ArrayList that is mutable!

Kotlin (图书馆):

class A {
  val items: List<Item> = ArrayList()
}

Java(消费者):

A a = new A();
a.getItems().add(new Item());   // Compiles and runs but I wish to fail or throw

How to make my Kotlin class fully immutable from Java perspective too?

推荐答案

All non-Mutable____ collections in Kotlin are compile time read-only types by default, but not immutable. See the following code snippet:

fun main(args: Array<String>) {
  // Explanation for ArrayList(listOf()) later down the post
  val list: List<Int> = ArrayList(listOf(1, 2, 3))
  println(list) // [1, 2, 3]

  // Fails at compile time
  // list.add(4)

  // Uh oh! This works at runtime!
  (list as MutableList<Int>).add(4)
  println(list) // [1, 2, 3, 4]
}

要想有一个不变的列表,请考虑番石榴的Immutable____个集合:

import com.google.common.collect.ImmutableList

fun main(args: Array<String>) {
  val list: List<Int> = ImmutableList.of(1, 2, 3)
  println(list) // [1, 2, 3]

  // Fails at compile time
  // list.add(4)

  // Fails at runtime, as expected
  (list as MutableList<Int>).add(4)
  println(list) // [1, 2, 3, 4]
}

请注意,Kotlin的一些标准运行时函数可能返回不可修改、不可调整大小等的集合,因此当您将只读集合直接强制转换为可变集合时,所有赌注都会失效.

For example, listOf() currently (this may change in the future!) returns a java.util.Arrays.ArrayList around the array of vararg parameters via Arrays.asList(T...). This "list" can be modified, but elements can never be added or removed, as you cannot resize an array. See Arrays.asList(T...) javadoc for more information.

If you really want a mutable collection from any given collection, consider making a copy using .toMutableList(). This will work on any collection:

import com.google.common.collect.ImmutableList

fun main(args: Array<String>) {
  val list: List<Int> = ImmutableList.of(1, 2, 3)

  val copy = list.toMutableList()
  copy.add(4)

  println(copy) // [1, 2, 3, 4]
  println(list) // [1, 2, 3]
}

Kotlin相关问答推荐

如果一项工作失败,请继续在Kotlin 等待其他工作/子元素完成

Kotlin—从列表中枚举属性计算不同值的数量

为什么在Spring中,对事务性方法调用的非事务方法调用仍然在事务中运行?

KMP:未能添加cafe.adriel.voyager依赖项

kotlin 模式匹配如何像 scala 一样工作

使用调度程序运行异步 Kotlin 代码

JetPack Compose:添加点击持续时间

如何在 kotlin 中使用带有泛型的密封类

kotest 更改环境变量

在 kotlin 中模拟伴随对象函数

SpringBoot 2.5.0 对于 Jackson Kotlin 类的支持,请在类路径中添加com.fasterxml.jackson.module: jackson-module-kotlin

模拟异常 - 没有找到答案

如何在调试中修复 ClassNotFoundException: kotlinx.coroutines.debug.AgentPremain?

如何在 Kotlin 中使用 volatile

在构造函数中仅注入某些参数

Kotlin 具体化的泛型不会按计划保持类型

Kotlin:sealed class cannot "contain" data classes?

Android 与 Kotlin - 如何使用 HttpUrlConnection

使用主构造函数时使用Kotlin getter/setter

在 Kotlin 函数上使用 Mokito anyObject() 时,指定为非 null 的参数为 null