luk*_*kle 79 generics casting list kotlin
我想编写一个函数来返回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}
}
Run Code Online (Sandbox Code Playgroud)
当转换为List<*>to时List<Waypoint>,我收到警告:
未选中Cast:kotlin.collections.List to kotlin.colletions.List
我不知道如何实现它.在没有此警告的情况下实施此功能的正确方法是什么?
hot*_*key 148
在Kotlin中,一般情况下无法在运行时检查泛型参数(例如只检查a的项目List<T>,这只是一种特殊情况),因此将泛型类型转换为具有不同泛型参数的另一种类型将引发警告,除非cast位于方差范围内.
但是,有不同的解决方案:
您已经检查了类型,并且您确信演员阵容是安全的.鉴于这种情况,你可以取消此警告用@Suppress("UNCHECKED_CAST").
@Suppress("UNCHECKED_CAST")
val waypointList = list as? List<Waypoint> ?: return null
Run Code Online (Sandbox Code Playgroud)使用.filterIsInstance<T>()函数,它检查项类型并返回包含传递类型的项的列表:
val waypointList: List<Waypoint> = list.filterIsInstance<Waypoint>()
if (waypointList.size != list.size)
return null
Run Code Online (Sandbox Code Playgroud)
或在同一声明中相同:
val waypointList = list.filterIsInstance<Waypoint>()
.apply { if (size != list.size) return null }
Run Code Online (Sandbox Code Playgroud)
这将创建一个所需类型的新列表(从而避免未经检查的内部转换),引入一点开销,但同时它可以避免迭代遍历list和检查类型(list.foreach { ... }在行),所以它不会显.
编写一个检查类型的实用程序函数,如果类型正确则返回相同的列表,从而将转换(在编译器的视角中仍然未选中)封装在其中:
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> List<*>.checkItemsAre() =
if (all { it is T })
this as List<T>
else null
Run Code Online (Sandbox Code Playgroud)
用法:
val waypointList = list.checkItemsAre<Waypoint>() ?: return null
Run Code Online (Sandbox Code Playgroud)Ada*_*Kis 15
为了改进@hotkey 的答案,这是我的解决方案:
val waypointList = list.filterIsInstance<Waypoint>().takeIf { it.size == list.size }
Run Code Online (Sandbox Code Playgroud)
这为您提供了List<Waypoint>是否可以投射所有项目,否则为 null。
在泛型类的情况下,无法检查强制转换,因为类型信息在运行时被删除。但是您检查列表中Waypoint的所有对象是否都是s,因此您可以使用@Suppress("UNCHECKED_CAST").
为避免此类警告,您必须将 a Listof objects 可转换为Waypoint. 当您正在使用*但试图将这个列表作为类型列表访问时,您将始终需要一个强制转换,并且这个强制转换将被取消选中。
小智 6
当用于检查可序列化到列表对象时,我对@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
Run Code Online (Sandbox Code Playgroud)