[英]Getting Exception when Safe-Casting to Generic Type in Kotlin
我在 kotlin ie 中使用安全轉換選項as?
當數據類型不兼容時,我仍然收到類轉換異常,當我通過編寫執行案例的通用方法執行此操作時會發生這種情況,但是如果我直接執行轉換,它會按預期從安全轉換中返回 null
class CastTest(val data: Any) {
fun castViaGenericMethod(): TypeA? {
return castToContext<TypeA>()
}
fun castDirectly(): TypeA? {
return data as? TypeA
}
private fun <CONTEXT> castToContext(): CONTEXT? = data as? CONTEXT
}
castViaGenericMethod()
-> 當數據不是TypeA
類型時,此方法拋出ClassCastException
。 castDirectly()
-> 當無法進行castDirectly()
時返回null
。
請建議如何做到這一點。
要解決您的問題,您可以使用reified
類型:
inline fun <reified CONTEXT> castToContext() = data as? CONTEXT
它沒有像您預期的那樣工作的原因是,泛型類型在運行時被刪除。
如果我們查看字節碼,我們會看到無論您的CONTEXT
泛型類型寫在哪里,它都會變成java/lang/Object
:
private final castToContext()Ljava/lang/Object;
L0
LINENUMBER 12 L0
ALOAD 0
GETFIELD CastTest.data : Ljava/lang/Object;
DUP
INSTANCEOF java/lang/Object // (1)
IFNE L1 // (1)
POP // (2)
ACONST_NULL // (2)
L1
ARETURN
L2
LOCALVARIABLE this LCastTest; L0 L2 0
MAXSTACK = 2
MAXLOCALS = 1
因此,安全轉換實際上會檢查給定的對象是否不是java/lang/Object
(1) 類型,如果是這種情況,則將要返回的值設置為null
。 但由於它是java/lang/Object
類型,因此該值只是按原樣返回。 然而,在調用端,字節碼如下所示:
LINENUMBER 4 L0
ALOAD 0
INVOKESPECIAL CastTest.castToContext ()Ljava/lang/Object; // the call
CHECKCAST TypeA // the type check
ARETURN
它在調用castToContext
之后做了一個額外的CHECKCAST TypeA
並且你得到你的ClassCastException
因為值沒有被取消(通用類型信息在運行時被刪除)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.