我想编写一个函数,它返回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>
时,我会收到警告:
未选中Cast:kotlin.collections.List 到kotlin.colletions.List
我无法找到实现它的方法。没有这个警告,实现这个功能的正确方法是什么?
答案 0 :(得分:117)
在Kotlin中,在一般情况下无法检查运行时的泛型参数(例如只检查List<T>
的项目,这只是一种特殊情况),因此转换为泛型类型对于具有不同通用参数的另一个参数,除非演员位于variance bounds内,否则将发出警告。
然而,有不同的解决方案:
您已经检查了类型,并且您确信演员阵容是安全的。鉴于此,您可suppress the warning使用@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
并检查类型(在{中{1}}行),所以它不会引人注意。
编写一个检查类型的实用程序函数,如果类型正确则返回相同的列表,从而将转换(从编译器的角度来看仍未选中)封装在其中:
list.foreach { ... }
用法:
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> List<*>.checkItemsAre() =
if (all { it is T })
this as List<T>
else null
答案 1 :(得分:3)
如果是泛型类,则无法检查强制转换,因为在运行时会删除类型信息。但是你检查列表中的所有对象都是Waypoint
,这样你就可以用@Suppress("UNCHECKED_CAST")
来抑制警告。
要避免此类警告,您必须传递List
可转换为Waypoint
的对象。当您使用*
但尝试将此列表作为输入列表进行访问时,您将始终需要进行投射,并且此投射将被取消选中。
答案 2 :(得分:0)
要改善@hotkey的答案,这是我的解决方案:
args.port = args.port || 8100;
args.target = args.target || "ie";//prior to this instead of "ie" it was "chrome"
如果可以投射所有项目,这会给您val waypointList = list.filterIsInstance<Waypoint>().takeIf { it.size == list.size }
,否则为null。
答案 3 :(得分:0)
当用于检查可序列化为列出对象时,我对@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
答案 4 :(得分:-1)
代替
myGenericList.filter { it is AbstractRobotTurn } as List<AbstractRobotTurn>
我喜欢做
myGenericList.filter { it is AbstractRobotTurn }.map { it as AbstractRobotTurn }
不确定性能如何,但至少没有警告。