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