DEVLOG 9.25 Kotlin泛型
Java中的泛型
Java中的泛型是不形變的,List<String> 并不是List<Object>的子類型。這樣做的一個好處是避免因為類型產(chǎn)生的異常(數(shù)組是形變的):
PECS: producer extends, consumer super
? extends E?表示此方法接受E和E的子類型??梢宰x(producer)不可以寫。因為已知是E的子類型,可以使用E承接(上轉(zhuǎn)型)
? super?E?表示此方法接受E和E的父類型,可以寫不可以讀 ???
Kotlin中的泛型
1. 泛型介紹
可以通過where指定類型參數(shù)T的范圍
2. 類型擦除
談到Java的類型擦除要說明兩個重點:
Java的List是不變的,數(shù)組是協(xié)變的。
Java的數(shù)組在運行時可以獲取自身的類型,但是List不行:
Kotlin中的泛型機制和Java中的相同。Java和Kotlin中的泛型在編譯之前會檢查類型是否存在問題,但是在編譯之后通過強制類型轉(zhuǎn)換等方式保證泛型特性。
如何在運行時獲取類型信息?
這種方式不能支持帶有類型參數(shù)的類獲取class對象。
使用匿名內(nèi)部類,匿名內(nèi)部類在初始化階段你就會綁定父類或者父接口的相應(yīng)信息:
使用Kotlin的特性打破類型不變!
在Java中下面的代碼是行不通的:
在Kotlin中以下的代碼是可以運行的:
這里需要說明一點,在Kotlin中的List和Java中的List定義不同:
比Java中多了out,(但是ArrayList是相同的)。也就是說Kotlin中的ArrayList<String>(List<String>)是List<Any>的子類型。
支持協(xié)變的List和它要付出的代價
如果支持協(xié)變的話會使得List存在安全問題。因為List<String>是List<Any>的子類型,然后往里面存儲內(nèi)容的時候可以放任何Any的子類。所以在Kotlin中,List并不能存儲內(nèi)容:

也就是說支持協(xié)變的List不能將類型參數(shù)作為方法參數(shù)
支持逆變的Comparator
Comparator需要支持逆變。

但是支持逆變的泛型類型參數(shù)不能作為方法的類型參數(shù)??紤]上面的情況,List<in T>可能會存入一個T的父類,向下轉(zhuǎn)型是不安全的。但是逆變不影響泛型參數(shù)作為方法的返回值。

所以總的來說和Java中類似,out支持協(xié)變,可以當(dāng)做producer;in支持逆變,可以當(dāng)做consumer。
可以這樣記:in->輸入-> 方法參數(shù) out->輸出->返回值