類型系統(tǒng)與可空類型
Kotlin屬于靜態(tài)類型編程語言,編程語言中類型系統(tǒng)定義:
如何將數(shù)值和表達(dá)式歸為不同類型
如何操作這些類型
這些類型之間如何相互作用
類型系統(tǒng)
1. 類型系統(tǒng)作用
讓編譯器檢查無意義、無效、類型不匹配的錯誤代碼
代碼更好讀懂
利于抽象
char[] str = {'a','b','c'}抽象為String str = 'abc',也就是char[] 到 String的抽象。
2. Java類型系統(tǒng)
Java中類型分為基礎(chǔ)類型和引用類型。
8大基礎(chǔ)類型,在使用的時候,內(nèi)存是分配在棧上的。不能在泛型中使用基礎(chǔ)類型,基礎(chǔ)類型不能為null。
引用類型,內(nèi)存分配在堆上。泛型中可以使用,可以為null。
基礎(chǔ)類型基于棧分配內(nèi)存速度快,使用上方便(不用new),但一定程度上破壞了面向?qū)ο笏枷?.
3. Kotlin的類型系統(tǒng)

通過顯示聲明可空類型,可以在編譯器減少NullPointerException
| Kotlin | Java |
|---|---|
| Int | int |
| Int? | Integer |
| Long | long |
| Long? | Long |
| ... | ... |
Java中基礎(chǔ)類型可以自動裝箱成對應(yīng)的包裝類型,包裝類型也可以拆箱為基礎(chǔ)類型。同理Kotlin中可空類型和非空類型之間也可以裝箱拆箱。拆箱會在編譯器完成,也就是說都是使用棧內(nèi)存。

書上寫 Int?之間‘===’返回的是false,但是測試了返回依然是true。

換個測試方法,如上如,返回的又是false了。
我的乖乖,這是啥子操作。裝箱拆箱這一塊參考>https://blog.csdn.net/fzhhsa/article/details/83278321
在范圍是 [-128, 127] 之間的數(shù)裝箱時并不會創(chuàng)建新的對象,所以這里a1和a2裝箱后的對象是同一個,a1 === a2也就返回true了。這里改為128或-129就又會變成false了。
對于數(shù)組,java中的類型是T[],Kotlin中使用Array代表數(shù)組類型

可空類型
為了避免不必要的空指針異常,kotlin使用了Elvis運(yùn)算符替代Java8的Optional
fun strLength(s : String?) : Int{
return s?.length ?:0 // ?.是安全調(diào)用符, ?:是Elvis從操作符
}
特殊類型
Unit、Any、Nothing及其對應(yīng)的可空類型Unit!、Any!、Nothing!
- Unit對應(yīng)Java中的Void,函數(shù)返回值為Unit的時候可以省略。

- Nothing,Java中void的包裝類Void,在Android的AsyncTask中使用到了,用于泛型中可能返回的Void。Void對應(yīng)Kotlin中的Nothing?,唯一可能的值是null。

Nothing類的定義構(gòu)造器是私有的,如果使用Nothing作為返回值,將拋出異常。Unit與Nothing之間的區(qū)別是,Unit類型表達(dá)式計算結(jié)果的返回 類型是Unit; Nothing類型的表達(dá)式計算結(jié)果是永遠(yuǎn)不會返回的(與 Java中的void相同)。
Nothing?在使用的時候只能被賦值為null,
- Any,Any是不可空類型的根,Any?是可空類型的根。

類型檢測和類型轉(zhuǎn)換
類型檢測
is運(yùn)算符相當(dāng)于java中的instanceof
fun test5(){
var f = Father()
var s = Son()
var fs :Father = s
println(f is Father) // true
println(s is Father) // true, 子類對象 is 父類類型
println(fs is Son) // true, 父類引用(子類對象) is 子類類型
}
類型轉(zhuǎn)換
在Java代碼中,當(dāng)我們使用str instanceof String來判斷其值為true的時候,我們想使用str變量,還需要顯式地強(qiáng)制轉(zhuǎn)換類型:

而在Kotlin中不需要這么做,編譯器會幫你解決
@Test
fun test6(){
val any : Any = "hhh"
if(any is String)
println(any.length)
else if(any is Number)
println(any.toString().length)
else if(any is Boolean)
println(1)
else
println("Not a String")
}
as運(yùn)算符
@Test
fun test5(){
var f = Father()
val s = Son()
val fs :Father = s
val sf : Son = fs as Son // 父類引用的子類對象轉(zhuǎn)化為子類引用
}