![](/img/trans.png)
[英]Kotlin (Mutable)List<(raw) kotlin.Any?> cast to List<JsonObject>
[英]Kotlin: How to work with List casts: Unchecked Cast: kotlin.collections.List<Kotlin.Any?> to kotlin.colletions.List<Waypoint>
我想編寫一個函數,該函數返回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>
,收到警告:
未經檢查的演員表:kotlin.collections.List到kotlin.colletions.List
我想不通其他方法來實現它。 在沒有此警告的情況下實現此功能的正確方法是什么?
在Kotlin中,一般情況下無法在運行時檢查泛型參數(例如僅檢查List<T>
,這只是一種特殊情況),因此將泛型轉換為具有不同泛型參數的另一個將引發警告除非強制轉換在方差范圍內 。
但是,有不同的解決方案:
您已經檢查了類型,並確定轉換是安全的。 鑒於此,您可以使用@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.foreach { ... }
遍歷該list
並檢查類型(在list.foreach { ... }
行),因此不會引起注意。
編寫一個檢查類型的實用程序函數,如果類型正確,則返回相同的列表,從而將類型轉換(從編譯器的角度來看仍未選中)封裝在其中:
@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
在泛型類的情況下,由於在運行時會擦除類型信息,因此無法檢查強制類型轉換。 但是您要檢查列表中的所有對象都是Waypoint
因此可以使用@Suppress("UNCHECKED_CAST")
取消警告。
為了避免此類警告,您必須傳遞可轉換為Waypoint
的對象List
。 當您使用*
但嘗試以類型列表訪問此列表時,將始終需要強制轉換,並且此強制轉換將被取消選中。
為了改善@hotkey的答案,這是我的解決方案:
val waypointList = list.filterIsInstance<Waypoint>().takeIf { it.size == list.size }
如果可以投射所有項目,這將為您提供List<Waypoint>
,否則為null。
當用於檢查可序列化到列表對象時,我對@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
代替
myGenericList.filter { it is AbstractRobotTurn } as List<AbstractRobotTurn>
我喜歡做
myGenericList.filter { it is AbstractRobotTurn }.map { it as AbstractRobotTurn }
不確定性能如何,但至少沒有警告。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.