繁体   English   中英

Kotlin:如何使用列表演员表:未选中的演员表:kotlin.collections.List <Kotlin.Any?> 到kotlin.colletions.List <Waypoint>

[英]Kotlin: How to work with List casts: Unchecked Cast: kotlin.collections.List<Kotlin.Any?> to kotlin.colletions.List<Waypoint>

我想编写一个函数,该函数返回List中的每个项目,而不是第一个或最后一个项目(通过点)。 该函数获取通用List<*>作为输入。 仅当列表中的元素属于Waypoint类型时,才应返回结果:

fun getViaPoints(list: List<*>): List<Waypoint>? {

    list.forEach { if(it !is Waypoint ) return null }

    val waypointList = list as? List<Waypoint> ?: return null

    return waypointList.filter{ waypointList.indexOf(it) != 0 && waypointList.indexOf(it) != waypointList.lastIndex}
}

List<*>强制转换为List<Waypoint> ,收到警告:

未经检查的演员表:kotlin.collections.List到kotlin.colletions.List

我想不通其他方法来实现它。 在没有此警告的情况下实现此功能的正确方法是什么?

在Kotlin中,一般情况下无法在运行时检查泛型参数(例如仅检查List<T> ,这只是一种特殊情况),因此将泛型转换为具有不同泛型参数的另一个将引发警告除非强制转换在方差范围内

但是,有不同的解决方案:

  • 您已经检查了类型,并确定转换是安全的。 鉴于此,您可以使用@Suppress("UNCHECKED_CAST") 取消警告

     @Suppress("UNCHECKED_CAST") val waypointList = list as? List<Waypoint> ?: return null 
  • 使用.filterIsInstance<T>()函数,该函数检查项目类型并返回带有已传递类型的项目的列表:

     val waypointList: List<Waypoint> = list.filterIsInstance<Waypoint>() if (waypointList.size != list.size) return null 

    或在一个陈述中相同:

     val waypointList = list.filterIsInstance<Waypoint>() .apply { if (size != list.size) return null } 

    这将创建所需类型的新列表(从而避免在内部进行未经检查的转换),从而带来一些开销,但与此同时,它使您list.foreach { ... }遍历该list并检查类型(在list.foreach { ... }行),因此不会引起注意。

  • 编写一个检查类型的实用程序函数,如果类型正确,则返回相同的列表,从而将类型转换(从编译器的角度来看仍未选中)封装在其中:

     @Suppress("UNCHECKED_CAST") inline fun <reified T : Any> List<*>.checkItemsAre() = if (all { it is T }) this as List<T> else null 

    用法:

     val waypointList = list.checkItemsAre<Waypoint>() ?: return null 

在泛型类的情况下,由于在运行时会擦除类型信息,因此无法检查强制类型转换。 但是您要检查列表中的所有对象都是Waypoint因此可以使用@Suppress("UNCHECKED_CAST")取消警告。

为了避免此类警告,您必须传递可转换为Waypoint的对象List 当您使用*但尝试以类型列表访问此列表时,将始终需要强制转换,并且此强制转换将被取消选中。

为了改善@hotkey的答案,这是我的解决方案:

val waypointList = list.filterIsInstance<Waypoint>().takeIf { it.size == list.size }

如果可以投射所有项目,这将为您提供List<Waypoint> ,否则为null。

当用于检查可序列化到列表对象时,我对@hotkey答案做了一些改动:

    @Suppress("UNCHECKED_CAST")
    inline fun <reified T : Any> Serializable.checkSerializableIsListOf() =
        if (this is List<*> && this.all { it is T })
          this as List<T>
        else null

代替

myGenericList.filter { it is AbstractRobotTurn } as List<AbstractRobotTurn>

我喜欢做

myGenericList.filter { it is AbstractRobotTurn }.map { it as AbstractRobotTurn }

不确定性能如何,但至少没有警告。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM