Kotlin中如何获取带泛型参数的Class<Foo<Bar>>类型实例?
解决方案
JVM的泛型基于擦除实现,运行时Boxed<Bar>和原始类型Boxed的Class实例完全相同,你只需要对无泛型参数的类字面量做一次强制类型转换即可解决编译错误,不需要修改任何现有正常子类的代码:
class BarParser : BaseParser<Boxed<Bar>>( @Suppress("UNCHECKED_CAST") Boxed::class.java as Class<Boxed<Bar>> ) { override fun parse(s: String): Boxed<Bar> { return Boxed(gson.fromJson(s, Bar::class.java)) } }
@Suppress("UNCHECKED_CAST)用于抑制编译器的未检查转换警告,该操作完全安全:运行时Class对象不携带泛型参数信息,不存在泛型参数不同导致的类型转换异常。- 原有非泛型参数的Parser子类(如FooParser)不需要做任何修改,完全兼容现有实现。
可选优化(不影响现有子类)
如果不想每次实现带泛型参数的Parser时都手动强转,可以给基类新增一个带实化泛型参数的辅助构造方法,原有子类的初始化逻辑完全不受影响:
class BaseParser<U : Any> ( private val clazz: Class<U> ) { // 新增辅助构造方法 constructor() : this(getGenericClass()) companion object { private inline fun <reified U> getGenericClass(): Class<U> { @Suppress("UNCHECKED_CAST") return U::class.java as Class<U> } } // 原有逻辑保持不变 open fun parse(s: String): U { return gson.fromJson(s, clazz) } // 其他原有方法不变 }
后续实现带泛型参数的Parser时可以直接省略构造参数:
class BarParser : BaseParser<Boxed<Bar>>() { override fun parse(s: String): Boxed<Bar> { return Boxed(gson.fromJson(s, Bar::class.java)) } }
内容的提问来源于stack exchange,提问作者azarkon
相关产品推荐
相关产品推荐

