【问题标题】:Cannot check for instance of erased type: List<Occupation_Info>无法检查已擦除类型的实例:List<Occupation_Info>
【发布时间】:2021-09-14 20:23:30
【问题描述】:

在函数中获取列表时出错

fun insert(insert_info_list: List<Any>){
    viewModelScope.launch(Dispatchers.IO) {
        when(insert_info_list){
            is List<Occupation_Info> ->{
               insert_info_list.forEach {
                   var show_occupation_info=Occupation_Info(it.occupation_id,it.fn,it.fv)
                   db.daoOccupationInfo().insertOrUpdate(show_occupation_info)
               }
           }
        }
    }
}

【问题讨论】:

    标签: android kotlin


    【解决方案1】:

    Kotlin 在编译时确保涉及泛型的操作的类型安全,而在运行时,泛型类型的实例不保存有关其实际类型参数的信息。例如,List 被擦除为 List。通常,无法在运行时检查实例是否属于具有特定类型参数的泛型类型。

    Documentation you need

    【讨论】:

      【解决方案2】:

      这是因为type erasure

      要绕过它,一种选择是将类型检查移到循环内。这并不完全等同于您在上面尝试做的事情,所以要小心。您可能有一个对象列表,其中一些对象实现了多种类型。

      在下面的代码中,我删除了您对 Dispatcher 的指定,因为如果您将 DAO 函数标记为 suspend,则没有必要。

      fun insert(insert_info_list: List<Any>){
          viewModelScope.launch {
              for (item in insert_info_list) {
                  when(item) {
                      is Occupation_Info -> {
                         var show_occupation_info = Occupation_Info(item.occupation_id, item.fn, item.fv)
                         db.daoOccupationInfo().insertOrUpdate(show_occupation_info)
                      }
                      // is...
                  }
              }
          }
      }
      

      或者您可以将输入列表的类型具体化,以便您检查它。这样做的缺点是调用站点的编译器必须知道列表的类型。

      inline fun <reified T> insert(insert_info_list: List<T>){
          viewModelScope.launch {
              @Suppress("UNCHECKED_CAST")
              when (T::class) {
                  Occupation_Info::class -> (for item in (insert_info_list as List<Occupation_Info>)) {
                     var show_occupation_info = Occupation_Info(item.occupation_id, item.fn, item.fv)
                     db.daoOccupationInfo().insertOrUpdate(show_occupation_info)
                  }
                  // SomethingElse::class...
              }
          }
      }
      

      可能最好的解决方案是为您想要支持的每种类型的列表设置单独的insert 函数,这样您就不必进行类型检查,这是一种代码异味。如果您对处理的每种类型的列表都执行了一些通用操作,则可以将该通用代码分解为每个插入函数调用的私有函数。

      【讨论】:

      • 你用的是哪个?我列出了三种不同的解决方案。从设计的角度来看,第三个是最好的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      • 2013-10-02
      • 1970-01-01
      相关资源
      最近更新 更多