接上文: Kotlin笔记12-Java和Kotlin中的范型对比(一)
Java中的范型类型,由于类型擦除的原因,无法在运行时访问范型T的类型。
在oracle官网的文档介绍中,也有提到类型擦除和Reifiable Types: https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.7,其中提到Java也会保留一些原始的类型信息,比如一个List<String>, 虽然经过类型擦除会变为List<Object>, 但是List的类型还是保留了下来。
本文主要介绍 通过使用inline函数和refined关键字 ---来保留范型类型T。
首先来一段Kotlin中文网对于Kotlin类型擦除的描述:
类型擦除
Kotlin 为泛型声明用法执行的类型安全检测仅在编译期进行。 运行时泛型类型的实例不保留关于其类型实参的任何信息。 其类型信息称为被擦除。例如,Foo<Bar>
与 Foo<Baz?>
的实例都会被擦除为 Foo<*>
。
因此,并没有通用的方法在运行时检测一个泛型类型的实例是否通过指定类型参数所创建 ,并且编译器禁止这种 is检测。
类型转换为带有具体类型参数的泛型类型,如 foo as List<String>
无法在运行时检测。 当高级程序逻辑隐含了类型转换的类型安全而无法直接通过编译器推断时, 可以使用这种非受检类型转换。编译器会对非受检类型转换发出警告,并且在运行时只对非泛型部分检测(相当于 foo as List<*>
)。
泛型函数调用的类型参数也同样只在编译期检测。在函数体内部, 类型参数不能用于类型检测,并且类型转换为类型参数(foo as T
)也是非受检的。然而, 内联函数的具体化的类型参数会由调用处内联函数体中的类型实参所代入,因此可以用于类型检测与转换, 与上述泛型类型的实例具有相同限制。
从上文中,可以得知,我们在需要类型检测和转换时,可以使用具体化的类型参数。
本来想继续写下去,但是在掘金上看到了几篇很好的文章,所以也就不多做介绍了,大家直接移步吧
[译]Kotlin的独门秘籍Reified实化类型参数(上篇)
Kotlin的独门秘籍Reified实化类型参数(下篇)
[译]Kotlin泛型中何时该用类型形参约束?