[英]Kotlin: Generic types in Kotlin
要獲取要用於例如 json 反序列化的類定義,可以在 Kotlin 中使用以下內容:
Map::class.java
一個示例用法如下:
val map = mapper.readValue(json, Map::class.java)
但是現在如何定義泛型類型呢?
像這樣的東西不能編譯:
val map = mapper.readValue(decodedString, Map<String, String>::class.java)
所以我的問題是: *::class.java
的通用等價物是什么?
Class<T>
(在 Java 中)或KClass<T>
(在 Kotlin 中)只能表示classes ,而不是所有類型。 如果您使用的 API 僅使用Class<T>
或KClass<T>
,它根本不支持泛型類型(至少在那些函數中)。
相反, KType (或 Java 中的Type
)是用於表示包括泛型在內的完整類型信息的正確類型。 你可以這樣使用它:
val myMapType: KType = typeOf<Map<String,String>>()
不幸的是, KType
沒有類型參數(它不是KType<T>
),這使得它無法用於編譯時類型檢查:你不能擁有相當於fun deserialize(Input, KClass<T>): T
使用KType
而不是KClass
,因為您不能僅使用KType
參數為返回類型定義T
。
有幾個技巧可以解決這個問題:
在 Java 和 Kotlin 中,一種方法是通過提供泛型超類並從其繼承來通過繼承獲取此信息。
一般來說,序列化 API(尤其是反序列化部分)提供了使用它的解決方法,例如 Jackson 的TypeReference或 Gson 的TypeToken 。 它基本上是他們的Type
版本,但帶有類型參數以具有一些編譯時類型安全性。
在 Kotlin 中,有時根據情況還有另一種方法:使用具體類型參數。 使用內聯函數,編譯器可以在編譯時了解更多關於類型參數的信息,方法是在內聯函數體時將它們替換為調用站點的實際推斷類型。 這允許像T::class
這樣的東西在內聯函數的主體中。 這就是你如何獲得像typeOf這樣的函數來獲得KType
的方法。
一些 Kotlin 特定的反序列化庫 API 使用內聯函數來消除用戶的麻煩,並直接獲取類型信息。 這就是jackson-module-kotlin通過提供不帶Class
參數的內聯readValue
擴展來實現的,它具體化類型參數以獲取目標類型信息
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.