programing

Kotlin: 목록 캐스팅을 사용하는 방법:선택되지 않은 캐스트: kotlin.collections입니다.kotlin.colutions에 등록합니다.목록입니다.

telecom 2023. 4. 25. 21:52
반응형

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>모든 항목을 캐스팅할 수 있는 경우, 그렇지 않은 경우 특수합니다.

범용 클래스의 경우 유형 정보가 런타임에 지워져 캐스트를 확인할 수 없습니다.그러나 목록의 모든 개체가 다음과 같은지 확인합니다.Waypoints를 사용하여 경고를 억제할 수 있습니다.@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 입니다.

반응형