Kotlin泛型擦除 List<Occupation_Info>类型校验报错如何解决
报错原因
这个报错是JVM泛型擦除机制直接导致的:
- Kotlin的泛型实现遵循JVM的泛型擦除规则,运行时不会保留泛型的类型参数信息,也就是说
List<Occupation_Info>和List<String>等所有列表类型在运行时都会被擦除为原始类型List,无法区分具体的泛型参数类型。 - 你代码中用
is List<Occupation_Info>判断列表的具体泛型类型,编译器判定这种判断在运行时无法生效,因此直接抛出该错误拦截非法操作。
解决方案
可以根据你的业务场景选择以下任意一种方案:
方案1:校验列表元素类型(无需修改函数签名)
不直接判断列表的泛型类型,转而判断列表内元素的实际类型,手动验证后做类型转换即可,适合无法修改函数入参声明的场景:
fun insert(insert_info_list: List<Any>){ viewModelScope.launch(Dispatchers.IO) { // 空列表可根据业务需求调整判断逻辑,比如跳过处理或者默认走对应分支 if (insert_info_list.isNotEmpty() && insert_info_list.first() is Occupation_Info) { // 已经手动校验过元素类型,压制unchecked cast警告即可 @Suppress("UNCHECKED_CAST") val occupationList = insert_info_list as List<Occupation_Info> occupationList.forEach { val show_occupation_info = Occupation_Info(it.occupation_id,it.fn,it.fv) db.daoOccupationInfo().insertOrUpdate(show_occupation_info) } } } }
方案2:使用具体化类型参数(reified)
如果允许调整函数声明,可以用inline + reified让泛型参数类型在运行时可获取,避免擦除问题:
inline fun <reified T> insert(insert_info_list: List<T>){ viewModelScope.launch(Dispatchers.IO) { if (T::class == Occupation_Info::class) { @Suppress("UNCHECKED_CAST") val occupationList = insert_info_list as List<Occupation_Info> occupationList.forEach { val show_occupation_info = Occupation_Info(it.occupation_id,it.fn,it.fv) db.daoOccupationInfo().insertOrUpdate(show_occupation_info) } } // 其他泛型类型的处理分支可以在此处扩展 } }
方案3:函数重载(最安全的编译期解决方案)
如果业务上不同类型的列表插入逻辑差异较大,建议直接重载不同参数类型的insert函数,编译期就能确定调用逻辑,完全不需要运行时类型判断:
// 专门处理Occupation_Info类型列表的插入 fun insert(insert_info_list: List<Occupation_Info>){ viewModelScope.launch(Dispatchers.IO) { insert_info_list.forEach { val show_occupation_info = Occupation_Info(it.occupation_id,it.fn,it.fv) db.daoOccupationInfo().insertOrUpdate(show_occupation_info) } } } // 其他类型列表的insert重载可以继续扩展 // fun insert(insert_info_list: List<OtherType>){...}
内容的提问来源于stack exchange,提问作者vivek singh
相关产品推荐
相关产品推荐

