Kotlin: 목록 캐스팅을 사용하는 방법:선택되지 않은 캐스트: kotlin.collections입니다.kotlin.colutions 에 등록합니다.목록입니다.
A의 모든 항목을 반환하는 함수를 작성하려고 합니다.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입니다.kotlin.colutions에 등록합니다.목록.
다른 방법으로는 실행할 방법을 찾을 수 없습니다.이 경고 없이 이 기능을 구현하는 올바른 방법은 무엇입니까?
Kotlin에서는 일반적인 경우 런타임에 일반 매개 변수를 확인할 수 있는 방법이 없습니다(예: 의 항목을 확인하는 것).List<T>
(이것은 특수한 경우일 뿐이므로, 다른 일반 매개 변수를 사용하여 일반 유형을 다른 유형으로 캐스팅하면 캐스트가 분산 범위 내에 있지 않는 한 경고가 발생합니다.
그러나 다음과 같은 다른 솔루션이 있습니다.
유형을 확인했으며 캐스팅이 안전한지 확인했습니다.이 경우 다음 방법으로 경고를 억제할 수 있습니다.
@Suppress("UNCHECKED_CAST")
.@Suppress("UNCHECKED_CAST") val waypointList = list as? List<Waypoint> ?: return null
항목 유형을 확인하고 전달된 유형의 항목이 포함된 목록을 반환하는 함수를 사용합니다.
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 { ... }
선)으로 표시되므로 눈에 띄지 않습니다.유형을 확인하고 유형이 맞으면 동일한 목록을 반환하는 유틸리티 함수를 작성하여 캐스트를 캡슐화합니다(컴파일러 관점에서 여전히 선택되지 않음).
@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
@hotkey의 답변을 개선하기 위해 다음과 같은 솔루션을 제공합니다.
val waypointList = list.filterIsInstance<Waypoint>().takeIf { it.size == list.size }
이렇게 하면 다음과 같습니다.List<Waypoint>
모든 항목을 캐스팅할 수 있는 경우, 그렇지 않은 경우 특수합니다.
범용 클래스의 경우 유형 정보가 런타임에 지워져 캐스트를 확인할 수 없습니다.그러나 목록의 모든 개체가 다음과 같은지 확인합니다.Waypoint
s를 사용하여 경고를 억제할 수 있습니다.@Suppress("UNCHECKED_CAST")
.
이러한 경고를 방지하려면 다음을 통과해야 합니다.List
변환할 수 있는 개체의 수입니다.Waypoint
사용할 때 사용합니다.*
하지만 이 목록에 입력된 목록으로 액세스하려면 항상 캐스팅이 필요하며 이 캐스팅은 선택 해제됩니다.
Serializable to List 개체를 확인하는 데 사용할 때 @hotkey answer를 약간 변경했습니다.
@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 }
성능이 어느 정도인지는 모르겠지만 최소한 경고는 없습니다.
Kotlin은 컴파일 시 제네릭을 포함하는 작업에 대한 유형 안전을 보장하며, 실행 시 일반 유형의 인스턴스는 실제 유형 인수에 대한 정보를 보유하지 않습니다.예를 들어, List는 List<*>로 지워집니다.일반적으로 런타임에 특정 형식 인수가 있는 일반 유형에 인스턴스가 속하는지 확인할 수 있는 방법은 없습니다.
https://kotlinlang.org/docs/typecasts.html#type-erasure-and-generic-type-checks
언급URL : https://stackoverflow.com/questions/36569421/kotlin-how-to-work-with-list-casts-unchecked-cast-kotlin-collections-listkot 입니다.
'programing' 카테고리의 다른 글
파일에서 특정 줄에 대한 커밋 로그를 검색하시겠습니까? (0) | 2023.04.25 |
---|---|
다양한 MessageBoxImage 또는 MessageBoxIcon의 이미지를 가져오려면 어떻게 해야 합니까? (0) | 2023.04.25 |
실패할 때까지 셸 명령을 반복적으로 실행하시겠습니까? (0) | 2023.04.25 |
UITableView 섹션 헤더의 글꼴 크기를 변경합니다. (0) | 2023.04.25 |
여러 bash 스크립트에서 pushd/popd 스택을 표시하지 않습니다(quiet pushd/popd). (0) | 2023.04.25 |