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

У меня проблема взаимодействия Java / Kotlin. Неизменяемый список Kotlin скомпилирован в обычный java.util.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?

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

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

Чтобы действительно иметь непреложный список, рассмотрите коллективные коллекции Guava's 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] }