一天入門Kotlin學習筆記(七)-泛型

前言

這節我們說下Kotlin的泛型。首先默認大家對Java泛型有個基本的認識,如果 不熟悉Java的泛型,可以閱讀文章,或是看下Java《Java核心技術卷一基礎知識第10版》中關於泛型章節的知識,講述的也很詳細。其實Kotlin的泛型和Java很相似。他們都是僞泛型,所謂僞泛型就是我們們是無法獲取到泛型的具體的類型的。以爲Java存在類型擦除和轉換。本篇還是和反射一樣,從實際代碼編寫角度,說下Kotlin的泛型

閱讀本文前建議閱讀文章:

《Java核心技術卷一基礎知識第10版》–泛型章節
java 泛型詳解

泛型的協變與逆變
Java 泛型之-協變&逆變

逆變與協變

泛型的逆變與協變其其在Java中也有。簡單概括來說就是<? extends T>實現了泛型的協變,<? super T>實現了泛型的逆變。具體的這兩種有什麼特性可以看開頭兩篇文章。

Kotlin中的協變與逆變

  • 泛型參數即可作爲傳入的參數,也可以作爲返回值,但被in和out關鍵字修飾後就不一樣了
  • out 叫協變 只能作爲返回值讀取 不能寫入和修改(Kotlin的list中只有get方法 沒有add)
  • in 叫逆變 只能寫入不能讀取 只能作爲參數傳入 (Kotlin中的Comparable只能傳入參數)
  • 不變 既沒有in也沒有out就叫做不變 如MutableList(相當於java中的list)
  • 協變點:返回值類型是泛型類型參數
  • 逆變點:入參類型是泛型參數的類型
  • @UnsafeVariance 型變點僞例(當時協變的時候 泛型作爲參數入參會報錯 那麼如果我們想忽略這個錯誤那麼我就可以用這個註解標識)

代碼示例:

協變 :泛型類型與實參的類型的繼承關係相同
   val listOf: List<Number> = listOf<Int>(1, 2, 3)

在泛型參數前面加上out表示協變,作爲返回值,爲只讀類型,
它的子類的泛型參數的類型是父類的泛型參數類型的子類,也就是說泛型參數的繼承關係與類的繼承關係保持一致(所以叫協變),比如Number是Int的父類 那麼List也是List父類型;

逆變 泛型參數的繼承關係與類的繼承關係相反
    val value: Comparable<Int> = object : Comparable<Any> {
        override fun compareTo(other: Any): Int {
            return 0
        }
    }

在泛型參數前面加上in表示逆變,作爲傳入的參數,爲只寫類型,它的泛型參數的繼承關係與類的繼承關係相反,比如父類是Any,子類是Int。

不變 類型必須保持一致 泛型之間沒有關係
    val mutableList: MutableList<Int> = mutableListOf<Int>(1, 2, 3)
星投影 其本質就是類似Java中通配符 ?
 val listOf1: List<Number> = listOf(1, 2, 3)
    //這是可以的
    val listOf2: List<*> = listOf(1, 2, 3)
//    val listOf3: List<Number> = listOf<*>(1, 2, 3)//ERROR

    //這是可以的
    val value1: Comparable<*> = object : Comparable<Any> {
        override fun compareTo(other: Any): Int {
            return 0
        }
    }
    //可以
    val value2: Comparable<*> = object : Comparable<Int> {
        override fun compareTo(other: Int): Int {
            return 0
        }
    }
    //不可以
//    val value3: Comparable<Int> = object : Comparable<*> {//error
//        override fun compareTo(other: Int): Int {
//            return 0
//        }
//    }

//    val hello=Hello<*>//ERROR 因爲泛型實參時不能用*代替
    //java 是可以有弱類型的(目的是兼容1.5) Kotlin不可以 定義了泛型了 創建的時候就必須指定泛型

星投影只能只能作爲形參,不能作爲實參。

reified 關鍵字

reified單詞含義爲具體化的。用法

inline fun <reified T> testGenerics2() {
    println(T::class.java)
}

加上reified關鍵字就可以打印出來他的類型了,這是在Java中做不到的。

inline關鍵字的作用

inline表示內聯函數

  • inline 修飾符影響函數本身和傳給它的 lambda 表達式:所有這些都將內聯到調用處。
  • 內聯可能導致生成的代碼增加;不過如果我們使用得當(即避免內聯過大函數),性能上會有所提升,尤其是在循環中的“超多態(megamorphic)”調用處。
  • inline關鍵字的作用是 一個方法帶參數 同時這個方法中的參數是一個高階函數(也就是Lambda表達式),那麼inline可以提升性能

結語

其實泛型很難講清楚。就算講清楚了,也可能晦澀難懂。其實泛型掌握了編寫規則。多實踐,就好了。下篇講下Kotlin的協程

Github源碼直接運行,包含全部詳細筆記

發佈了33 篇原創文章 · 獲贊 8 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章