How to create an immutable list in Kotlin that is also an immutable list in Java?

前端 未结 1 1936
一生所求
一生所求 2021-01-11 10:36

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

Kotlin (library):

class          


        
1条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-01-11 11:26

    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) {
      // Explanation for ArrayList(listOf()) later down the post
      val list: List = 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).add(4)
      println(list) // [1, 2, 3, 4]
    }
    

    To truly have an immutable list, consider Guava's Immutable____ collections:

    import com.google.common.collect.ImmutableList
    
    fun main(args: Array) {
      val list: List = 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).add(4)
      println(list) // [1, 2, 3, 4]
    }
    

    Be aware that some of Kotlin's standard runtime function may return collections that are either unmodifiable, not resizable, etc., so all bets are off when you directly cast a read-only collection to a mutable one.

    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) {
      val list: List = ImmutableList.of(1, 2, 3)
    
      val copy = list.toMutableList()
      copy.add(4)
    
      println(copy) // [1, 2, 3, 4]
      println(list) // [1, 2, 3]
    }
    

    0 讨论(0)
提交回复
热议问题