<font face= 黑體>在 Kotlin 中的類與接口 中咱們已經講了 Kotlin 的 類、接口 和 擴展方法,今天咱們來說 Kotlin 中的 空類型安全 和 智能類型轉換。java
<font face= 黑體>Java 語言中是沒有空類型安全這一律唸的,因此寫 Java 代碼常常會出現空指針異常,可是 Kotlin 致力於消除空引用所帶來的危險,因此就有了空類型安全概念。git
<font face= 黑體>下面這段代碼在 Kotlin 中是沒法編譯經過的,由於 Kotlin 的 String 是不能接受空值的,因此這個賦值操做是不被容許的。github
var nonNull: String = "Hello" nonNull = null // 不可空類型,不能賦值爲 null // 訪問長度的話,不須要空判斷 val length = nonNull.length
<font face= 黑體>IDE 報錯以下所示:segmentfault
<font face= 黑體>可是若是咱們非得定義一個空值,也是有辦法的,Kotlin 爲了 100% 兼容 Java,必須得實現接收空值,因此要接收空值能夠在定義的時候加一個 ?。安全
<font face= 黑體>可是這個時候這個變量就多是空值,因此訪問的時候就會比較嚴格,好比下面代碼中的 nullable.length 就會報錯,由於可能觸發空指針異常。函數
var nullable: String? = "Hello" nullable = null // 可空類型,編譯經過 val length = nullable.length // 可能觸發空指針,編譯保報錯
<font face= 黑體>IDE 報錯以下所示:
<font face= 黑體>這個時候咱們想 nullable.length 不報錯能夠:this
<font face= 黑體>當咱們肯定 nullable 不可能爲空的時候,能夠將 nullable 強轉爲不可空類型,以下所示:spa
var nullable: String? = "Hello" // 不會報錯了(本身已經知道了,這個 nullable 不可能爲空) val length = nullable!!.length
<font face= 黑體>若是咱們不肯定 nullable 是否爲空的時候,能夠用 ?. 來實現安全訪問,以下所示:線程
var nullable: String? = "Hello" // 這種狀況下若是 nullable 爲空的話,那麼返回的 length 也是空 val length = nullable?.length // 這時候 length 的類型不是 Int,而是 Int?,因此能夠寫成下面這樣 val length: Int? = nullable?.length // 若是你想 length 的類型是 Int 的話,能夠加個默認值,寫成下面這樣 val length: Int = nullable?.length ?: 0 // 若是 nullable?.length 爲空, 就返回0
<font face= 黑體>咱們知道 Int 是 Number 的子類,因此經過下面的代碼咱們就能夠知道 String 應該是 String? 的子類。
var a: Int = 2 var b: Number = 10.0 a = b // Type mismatch,報錯 b = a // OK var x: String = "Hello" var y: String? = "World" x = y // Type mismatch,報錯 y = x // OK
<font face= 黑體>例子1:指針
<font face= 黑體>咱們先來寫一個 Java 的類型轉換:
// 定義一個接口 public interface Kotliner { }
// 定義一個類 Person 實現 Kotliner 接口 public class Person implements Kotliner { public final String name; public final int age; public Person(String name, int age) { this.name = name; this.age = age; } public static void main(String[] args) { // 用子類的實例賦值給接口的引用 Kotliner kotliner = new Person("Test", 20); // 這裏已經判斷了是否是 Person,可是下面仍是要強制類型轉換 if (kotliner instanceof Person) { System.out.println(kotliner.name); // 這樣寫報錯 System.out.println(((Person) kotliner).name); // 正確寫法 } } }
<font face= 黑體>一樣的代碼在 Kotlin 中就能夠實現智能類型轉換,不須要強制類型轉換:
val kotliner: Kotliner = Person("Test", 20) if (kotliner is Person) { println((kotliner as Person).name) // 不須要強轉,能夠智能轉換,因此下面的寫法就能夠了 println(kotliner.name) }
<font face= 黑體>例子2:
<font face= 黑體>下面這段代碼定義了一個 value, 類型是 String?,if 判斷其不爲空,因此在 if 判斷這個括號裏面,value 的類型會被智能轉換成 String,固然出了括號,value 的類型就又是 String? 了。
var value: String? = null value = "Test" if (value != null) { // value: String? ==> String println(value.length) } // value: String? ...
<font face= 黑體>下面這種狀況就不支持智能類型轉換,由於這個公共變量不少地方均可以訪問,因此咱們在判斷不爲空以後,有可能別的線程又把 tag 改爲了空,因此這種狀況智能類型轉換就失效了。
// 在 main 函數以外定義一個公共變量 var tag: String? = null fun main() { if(tag != null) { // 有可能被改爲空 println(tag.length) // 報錯,不支持智能類型轉換 } }
<font face= 黑體>本篇博客主要講了 Kotlin 中的空類型安全和智能類型轉換,下一節咱們講 Kotin 中的表達式。
源碼 已上傳至 github,有須要能夠直接下載。