Как создать неизменяемый список в Kotlin, который также является неизменяемым списком в Java?

у меня есть проблема взаимодействия Java/Kotlin. Неизменяемый список Kotlin компилируется в обычную java.утиль.ArrayList это изменчиво!

Котлин (библиотека):

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

Как сделать мой класс Kotlin полностью неизменяемым с точки зрения Java?

1 ответов


всеMutable____ коллекции в Котлине являются время компиляции, доступные только для чтения по умолчанию, но не неизменяемые. См. следующий фрагмент кода:

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 могут возвращать коллекции, которые либо не изменяются, либо не изменяются и т. д., поэтому все ставки отключены, когда вы непосредственно бросаете только для чтения коллекция к изменяемому.

например, listOf() в настоящее время (это может измениться в будущем!) возвращает java.util.Arrays.ArrayList вокруг массива параметров vararg через Arrays.asList(T...). Этот "список" может быть изменен, но элементы не могут быть добавлены или удалены, как вы не можете изменить размер массива. См.Arrays.asList(T...) javadoc для получения дополнительной информации.

если вы действительно хотите изменяемую коллекцию из любой данной коллекции, подумайте о создании копии с помощью .toMutableList(). Этот будет работать над любой коллекцией:

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]
}