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
:
I want to write a function that returns every item in a List
that is not the first or the last item (a via point). The function gets a generic List<*>
as input. A result should only be returned if the elements of the list are of the type 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
时,我收到警告:
When casting the List<*>
to List<Waypoint>
, I get the warning:
未经检查的演员表:kotlin.collections.List到 kotlin.colletions.List
Unchecked Cast: kotlin.collections.List to kotlin.colletions.List
否则我想不出实现它的方法.在没有此警告的情况下实现此功能的正确方法是什么?
I can't figure out a way to implement it otherwise. What's the right way to implement this function without this warning?
推荐答案
在 Kotlin 中,一般情况下没有办法在运行时检查泛型参数(就像只检查 List
,这只是一个特例),因此将泛型类型转换为具有不同泛型参数的另一个类型将引发警告,除非转换位于 方差界限.
In Kotlin, there's no way to check the generic parameters at runtime in general case (like just checking the items of a List<T>
, which is only a special case), so casting a generic type to another with different generic parameters will raise a warning unless the cast lies within variance bounds.
然而,有不同的解决方案:
There are different solutions, however:
您已经检查了类型并且您非常确定演员表是安全的.鉴于此,您可以使用 抑制警告代码>@Suppress("UNCHECKED_CAST").
You have checked the type and you are quite sure that the cast is safe. Given that, you can suppress the warning with
@Suppress("UNCHECKED_CAST")
.
@Suppress("UNCHECKED_CAST")
val waypointList = list as? List<Waypoint> ?: return null
使用.filterIsInstance
函数,它检查项目类型并返回包含传递类型的项目的列表:
Use .filterIsInstance<T>()
function, which checks the item types and returns a list with the items of the passed type:
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 { ... }
行中),所以它不会被注意到.
This will create a new list of the desired type (thus avoiding unchecked cast inside), introducing a little overhead, but in the same time it saves you from iterating through the list
and checking the types (in list.foreach { ... }
line), so it won't be noticeable.
编写一个实用程序函数来检查类型并在类型正确时返回相同的列表,从而将强制转换(从编译器的角度来看仍未检查)封装在其中:
Write a utility function that checks the type and returns the same list if the type is correct, thus encapsulating the cast (still unchecked from the compiler's point of view) inside it:
@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
这篇关于Kotlin:如何使用列表类型转换:未选中类型转换:kotlin.collections.List<Kotlin.Any?>到 kotlin.colletions.List<Waypoint>的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!