日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Kotlin学习:Kotlin泛型

發布時間:2023/12/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Kotlin学习:Kotlin泛型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Kotlin 泛型

泛型,即 "參數化類型",將類型參數化,可以用在類,接口,方法上。

與 Java 一樣,Kotlin 也提供泛型,為類型安全提供保證,消除類型強轉的煩惱。

聲明一個泛型類:

class Box<T>(t: T) {var value = t }

創建類的實例時我們需要指定類型參數

val box: Box<Int> = Box<Int>(1) // 或者 val box = Box(1) // 編譯器會進行類型推斷,1 類型 Int,所以編譯器知道我們說的是 Box<Int>。

以下實例向泛型類 Box 傳入整型數據和字符串

class Box<T>(t : T) {var value = t }fun main(args: Array<String>) {var boxInt = Box<Int>(10)var boxString = Box<String>("Runoob")println(boxInt.value)println(boxString.value) }

輸出結果為

10 Runoob

定義泛型類型變量,可以完整地寫明類型參數,如果編譯器可以自動推定類型參數,也可以省略類型參數。

Kotlin 泛型函數的聲明與 Java 相同,類型參數要放在函數名的前面

fun <T> boxIn(value: T) = Box(value)// 以下都是合法語句 val box4 = boxIn<Int>(1) val box5 = boxIn(1) // 編譯器會進行類型推斷

在調用泛型函數時,如果可以推斷出類型參數,可以省略泛型參數。

以下實例創建了泛型函數 doPrintln,函數根據傳入的不同類型做相應處理

fun main(args: Array<String>) {val age = 23val name = "runoob"val bool = truedoPrintln(age) // 整型doPrintln(name) // 字符串doPrintln(bool) // 布爾型 }fun <T> doPrintln(content: T) {when (content) {is Int -> println("整型數字為 $content")is String -> println("字符串轉換為大寫:${content.toUpperCase()}")else -> println("T 不是整型,也不是字符串")} }

輸出結果為

整型數字為 23 字符串轉換為大寫:RUNOOB T 不是整型,也不是字符串

泛型約束

我們可以使用泛型約束來設定一個給定參數允許使用的類型。

Kotlin 中使用 : 對泛型的類型上限進行約束。

最常見的約束是上界(upper bound)

fun <T : Comparable<T>> sort(list: List<T>) {// …… }

Comparable?的子類型可以替代 T。 例如

sort(listOf(1, 2, 3)) // OK。Int 是 Comparable<Int> 的子類型 sort(listOf(HashMap<Int, String>())) // 錯誤:HashMap<Int, String> 不是 Comparable<HashMap<Int, String>> 的子類型

默認的上界是 Any?

對于多個上界約束條件,可以用 where 子句

fun <T> copyWhenGreater(list: List<T>, threshold: T): List<String>where T : CharSequence,T : Comparable<T> {return list.filter { it > threshold }.map { it.toString() } }

型變

Kotlin 中沒有通配符類型,它有兩個其他的東西:聲明處型變(declaration-site variance)與類型投影(type projections)

聲明處型變

聲明處的類型變異使用協變注解修飾符:in、out,消費者 in, 生產者 out。

使用 out 使得一個類型參數協變,協變類型參數只能用作輸出,可以作為返回值類型但是無法作為入參的類型

// 定義一個支持協變的類 class Runoob<out A>(val a: A) {fun foo(): A {return a} }fun main(args: Array<String>) {var strCo: Runoob<String> = Runoob("a")var anyCo: Runoob<Any> = Runoob<Any>("b")anyCo = strCoprintln(anyCo.foo()) // 輸出 a }

in 使得一個類型參數逆變,逆變類型參數只能用作輸入,可以作為入參的類型但是無法作為返回值的類型

// 定義一個支持逆變的類 class Runoob<in A>(a: A) {fun foo(a: A) {} }fun main(args: Array<String>) {var strDCo = Runoob("a")var anyDCo = Runoob<Any>("b")strDCo = anyDCo }

星號投射

有些時候, 你可能想表示你并不知道類型參數的任何信息, 但是仍然希望能夠安全地使用它. 這里所謂"安全地使用"是指, 對泛型類型定義一個類型投射, 要求這個泛型類型的所有的實體實例, 都是這個投射的子類型。

對于這個問題, Kotlin 提供了一種語法, 稱為 星號投射(star-projection):

  • 假如類型定義為 Foo<out T> , 其中 T 是一個協變的類型參數, 上界(upper bound)為 TUpper ,Foo<> 等價于 Foo<out TUpper> . 它表示, 當 T 未知時, 你可以安全地從 Foo<> 中 讀取TUpper 類型的值.
  • 假如類型定義為 Foo<in T> , 其中 T 是一個反向協變的類型參數, Foo<> 等價于 Foo<inNothing> . 它表示, 當 T 未知時, 你不能安全地向 Foo<> 寫入 任何東西.
  • 假如類型定義為 Foo<T> , 其中 T 是一個協變的類型參數, 上界(upper bound)為 TUpper , 對于讀取值的場合, Foo<*> 等價于 Foo<out TUpper> , 對于寫入值的場合, 等價于 Foo<in Nothing> .

如果一個泛型類型中存在多個類型參數, 那么每個類型參數都可以單獨的投射. 比如, 如果類型定義為interface Function<in T, out U> , 那么可以出現以下幾種星號投射:

  • Function<*, String> , 代表 Function<in Nothing, String> ;
  • Function<Int, *> , 代表 Function<Int, out Any?> ;
  • Function<,?> , 代表 Function<in Nothing, out Any?> .
  • 注意: 星號投射與 Java 的原生類型(raw type)非常類似, 但可以安全使用

    總結

    以上是生活随笔為你收集整理的Kotlin学习:Kotlin泛型的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。