4.1 Java語言和Kotlin語言對比(2) 泛型和數組

4.1 Java語言和Kotlin語言對比(2)
注意Java中基礎類型的裝箱類型當用作類型參數時被映射成了平臺類型。
例如,List<java.lang.Integer> 在Kotlin中被映射成List<Int!>
集合類型在Kotlin中有可能是隻讀或者不可變的,所以Java的集合類型被映射如下:(本表中的所有Kotlin類型都在包kotlin.collections下)

Java type Kotlin read-only type Kotlin mutable type Loaded platform type
Iterator Iterator MutableIterator (Mutable)Iterator!
Iterable Iterable MutableIterable (Mutable)Iterable!
Collection Collection MutableCollection (Mutable)Collection!
Set Set MutableSet (Mutable)Set!
List List MutableList (Mutable)List!
ListIterator ListIterator MutableListIterator (Mutable)ListIterator!
Map Map MutableMap (Mutable)Map!
Map.Entry Map.Entry MutableMap.MutableEntry (Mutable)Map.(Mutable)Entry!

Java arrays 的映射如下:

Java type Kotlin type
int[] kotlin.IntArray!
String[] kotlin.Array<(out) String>!

Java泛型在Kotlin中的表示

Kotlin中的泛型和Java中略有不同。(詳見generics)。

  • 當把Java中的泛型類型引入到Kotlin的時候,做了如下轉換。
    • Foo<? extends Bar>變成了Foo<out Bar!>!
    • Foo<? super Bar> 變成了Foo<in Bar!>!
  • Java的raw types 被轉換成了star projections
    • List 變成了List<*>!。例如List<out Any?>!

和Java一樣,Kotlin的泛型在運行時也不能被retained 例如,對象在被當做類型參數被傳遞給構造函數的時候,沒有帶有類型信息。 例如,ArrayList<Integer>ArrayList<Character>沒有分別。這樣就無法使用is-check來判斷泛型。 Kotlin僅支持is-check 來判斷star-projected泛型。

if (a is List<Int>) // Error: cannot check if it is really a List of Ints
// but
if (a is List<*>) // OK: no guarantees about the contents of the list

JavaArrays

在Kotlin中Arrays是非協變的invariant, 和Java不同。這意味着無法把Array<String> 賦值給Array<Any>, 這可以防止一些潛在的運行時錯誤。在Kotlin中,把一個子類的數組當做一個父類的數組傳遞給一個函數是不允許的,但是傳遞給Java函數中是可以的(通過Array<(out) String>!)。

Java平臺上數組和基礎數據類型被用來減少裝箱/拆箱操作帶來消耗。 由於Kotlin隱藏了這些實現的細節,必須要使用一個規避方法來和Java代碼交互。這些就是對於每個基礎數據類型數組的特殊類型(IntArray, DoubleArray, CharArray 等)。這些類型和Array類型無關,並且被編譯成Java的基礎數組類型來獲得最好的性能。

假設下面的Java函數接受一個int 類型的數組

public class JavaArrayExample {

    public void removeIndices(int[] indices) {
        // code here...
    }
}

在Kotlin中可以傳一個基礎數據類型的數據當做參數

val javaObj = JavaArrayExample()
val array = intArrayOf(0, 1, 2, 3)
javaObj.removeIndices(array)  // passes int[] to method

當編譯成JVM代碼時,編譯器會優化數組的訪問,因此沒有引入額外的開銷。

val array = arrayOf(1, 2, 3, 4)
array[x] = array[x] * 2 // no actual calls to get() and set() generated
for (x in array) { // no iterator created
    print(x)
}

甚至在使用index 的時候,也沒有額外的開銷

for (i in array.indices) { // no iterator created
    array[i] += 2
}

最後in-checks 也沒有額外的開銷

if (i in array.indices) { // same as (i >= 0 && i < array.size)
    print(array[i])
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章