提问者:小点点

静态编程语言:如何使用列表强制转换:未经选中的强制转换:kotlin.集合。列表<Kotlin。任何?>到kotlin.同事。列表<航点>


我想编写一个函数,返回List中不是第一个或最后一个项目(via点)的每个项目。该函数得到一个通用的列表

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}
}

铸造列表时

未选中的演员:kotlin.集合.列表到kotlin.同事.列表

否则我想不出实现它的方法。没有这个警告,实现这个功能的正确方法是什么?


共3个答案

匿名用户

在静态编程语言中,在一般情况下,没有办法在运行时检查泛型参数(比如只检查List的项目)

然而,有不同的解决方案:

>

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

    @Suppress("UNCHECKED_CAST")
    val waypointList = list as? List<Waypoint> ?: return null
    

    使用. filterIsInstance

    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和检查类型(在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
    

  • 匿名用户

    为了改进@hotkey的答案,我的解决方案如下:

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

    这为您提供列表

    匿名用户

    对于泛型类,无法检查强制转换,因为类型信息在运行时被删除。但是您可以检查列表中的所有对象都是Waypoint,因此您可以使用@Suppress("UNCHECKED_CAST")来抑制警告。

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