簡體   English   中英

Kotlin:Kotlin 中的泛型類型

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM