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