
上QQ阅读APP看书,第一时间看更新
6.1.4 Kotlin如何获得声明的泛型类型
虽然Java使用了类型擦除来实现泛型,但是它生成的class文件中还是保存了泛型相关的信息。这些信息被保存在class字节码常量池中,使用泛型的代码会生成一个signature签名字段,该signature签名字段指明了这个常量池的地址,因此从该常量池中能够获取到具体的类型。
跟Java一样,Kotlin也是通过类型擦除支持泛型的。
由于运行时被擦除,因此会带来一些影响。那么如何使用Kotlin来解决这些问题呢?下面列举一些常用的方法。
1.匿名内部类获得泛型信息
Java可以使用匿名内部类的方式获取泛型参数的类型。

执行结果如下:
Generic1.Generic1$InnerClass<java.lang.Integer> class java.lang.Integer
Kotlin同样适用此方法。

执行结果如下:
generic.Generic1.generic.Generic1$InnerClass<java.lang.Integer> class java.lang.Integer
2.反射获得泛型信息
Java利用反射获取运行时泛型参数的类型,子类可以获取父类泛型的具体类型。

在Kotlin中也同样适用此方法。

3.声明内联函数,使其类型不被擦除
Kotlin能够支持泛型数组,它们不会协变,例如:
val array1 = arrayOf<Int>(1, 2, 3, 4) val array2 = arrayOf<String>("1", "2", "3", "4")
上述代码在定义两个数组时使用了arrayOf,它的源码如下:

可以发现arrayOf方法不仅使用inline修饰,还使用reified标记类型参数。于是,打印array1、array2的类型:
println(array1.javaClass) println(array2.javaClass)
执行结果如下:
class [Ljava.lang.Integer; class [Ljava.lang.String;
4.实例化类型参数代替类引用
再举一个Kotlin使用Gson的反序列化的例子,可以使用实例化类型参数T::class.java:
inline fun <reified T : Any> Gson.fromJson(json: String): T = Gson(). fromJson(json, T::class.java)
小结一下获得泛型类型的几种方式:
· 前面两种方式是Java获取泛型类型的方式,Kotlin也适用。
· Kotlin的泛型方法要能够获取泛型类型,必须使用inline以及reified标记类型参数。