2016-11-12 72 views
6

我有一個Java/Kotlin互操作問題。一個Kotlin不可變列表被編譯成一個可變的普通java.util.ArrayList!如何在Kotlin中創建一個也是Java中不可變列表的不可變列表?

科特林(庫):

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 

如何使我的科特林類從Java透視圖中也完全不變的?

+0

我不熟悉Kotlin,但番石榴Java庫有一個'ImmutableList'類型,您可以使用它來包裝可變的'ArrayList'。 – pathfinderelite

+1

unmodifiableList(ArrayList()) –

+1

Works。請將其張貼爲答案。 – WindRider

回答

10

所有非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] 
} 

要知道,有些科特林的標準運行功能可能返回或者是不可修改的集合,而不是可調整大小等等,所以當您直接將只讀集合轉換爲可變集合時,所有投注都將關閉。

例如,目前listOf()這可能在未來改變!)經由Arrays.asList(T...)返回的可變參數參數陣列周圍一個java.util.Arrays.ArrayList。這個「列表」可以修改,但元素永遠不能被添加或刪除,因爲你不能調整數組的大小。有關更多信息,請參閱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] 
} 
+0

Guava必須在Android上避免。 'Collections.unmodifiableList()'是最安全和最簡單的解決方案。 – WindRider

+0

@WindRider [Guava可以與Android一起使用就好了](http://stackoverflow.com/questions/14978699/is-it-a-good-idea-to-use-google-guava-library-for-android-開發),但建議使用ProGuard – kbolino

相關問題