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}
}
When casting the List<*>
to List<Waypoint>
, I get the warning:
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?
Best Answer
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:
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")
.Use
.filterIsInstance<T>()
function, which checks the item types and returns a list with the items of the passed type:or the same in one statement:
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 (inlist.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:
With the usage: