Kotlin:如何使用列表强制转换:未选中强制转换:Kotlin.collections.List<;科特林。有吗?>;至kotlin.Collections.List<;航路点>;

Kotlin:如何使用列表强制转换:未选中强制转换:Kotlin.collections.List<;科特林。有吗?>;至kotlin.Collections.List<;航路点>;,list,generics,casting,kotlin,List,Generics,Casting,Kotlin,我想编写一个函数,返回列表中不是第一个或最后一个项目(通过点)的每个项目。该函数获取一个通用的列表作为输入。仅当列表中的元素属于航路点类型时,才应返回结果: fun getViaPoints(list: List<*>): List<Waypoint>? { list.forEach { if(it !is Waypoint ) return null } val waypointList = list as? 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}
}
fun getViaPoints(list:list):list?{
list.forEach{如果(它!是航路点)返回null}
val waypointList=列表为?列表?:返回null
返回waypointList.filter{waypointList.indexOf(it)!=0&&waypointList.indexOf(it)!=waypointList.lastIndex}
}
列表
强制转换为
列表
时,我收到警告:

未选中的强制转换:kotlin.collections.List 至kotlin.Collections.List


我想不出别的方法来实现它。在没有此警告的情况下,实现此函数的正确方法是什么?

如果是泛型类,则无法检查强制转换,因为类型信息在运行时被擦除。但是您要检查列表中的所有对象是否都是
航路点
s,这样您就可以使用
@suppress(“UNCHECKED_CAST”)
来抑制警告


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

在Kotlin中,在一般情况下,无法在运行时检查通用参数(例如仅检查
列表的项,这只是一种特殊情况),因此,将泛型类型强制转换为具有不同泛型参数的另一个泛型类型将引发警告,除非强制转换位于

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

  • 您已经检查了类型,并且非常确定该演员阵容是安全的。鉴于此,您可以使用
    @Suppress(“UNCHECKED\u CAST”)

    使用时:

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

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

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

如果所有项目都可以强制转换,那么这将为您提供
列表
,否则为空。

当用于检查可序列化列表对象时,我对@hotkey answer做了一些修改:

    @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
@Suppress(“未选中的\u CAST”)
inline fun Serializable.checkSerializableiListof()=
if(这是List&&this.all{it is T})
这是一个列表
否则无效
而不是

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

不知道这有多好,但至少没有警告。

回答得很好!我选择list.filterIsInstance()解决方案,因为我认为它是最干净的解决方案。请注意,如果您使用,并且原始列表包含不同类型的元素,那么代码将自动过滤掉它们。有时这是您想要的,但有时您可能宁愿抛出一个
IllegalStateException
或类似的异常。如果是后者,那么您可以创建自己的方法来检查并强制转换:
inline fun Iterable.mapAsInstance()=map{it.apply{check(这是R)}as R}
注意,
.apply
不返回lambda的返回值,它返回接收对象。如果希望选项返回空值,您可能需要使用
.takeIf
。正在寻找类似的解决方案,但出现以下错误:
无法访问“Serializable”:它是“kotlin.io”中的内部解决方案。
解决方案:在android中,要传递用户定义的对象,您的类应该实现Parcelable而不是Serializable接口。
val waypointList = list.checkItemsAre<Waypoint>() ?: return null
val waypointList = list.filterIsInstance<Waypoint>().takeIf { it.size == list.size }
    @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 }