<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 空安全 [TOC] ## 可空類型與非空類型 Kotlin 的類型系統旨在消除來自代碼空引用的危險,也稱為[《十億美元的錯誤》](http://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions)。 許多編程語言(包括 Java)中最常見的陷阱之一,就是訪問空引用的成員會導致空引用異常。在 Java 中,這等同于 `NullPointerException` 或簡稱 `NPE`。 Kotlin 的類型系統旨在從我們的代碼中消除 `NullPointerException`。NPE 的唯一可能的原因可能是: * 顯式調用 `throw NullPointerException()`; * 使用了下文描述的 `!!` 操作符; * 有些數據在初始化時不一致,例如當: * 傳遞一個在構造函數中出現的未初始化的 *this*并用于其他地方(“**泄漏this**”); * [超類的構造函數調用一個開放成員](http://www.kotlincn.net/docs/reference/classes.html#%E6%B4%BE%E7%94%9F%E7%B1%BB%E5%88%9D%E5%A7%8B%E5%8C%96%E9%A1%BA%E5%BA%8F),該成員在派生中類的實現使用了未初始化的狀態; * Java 互操作: * 企圖訪問[平臺類型](http://www.kotlincn.net/docs/reference/java-interop.html#%E7%A9%BA%E5%AE%89%E5%85%A8%E4%B8%8E%E5%B9%B3%E5%8F%B0%E7%B1%BB%E5%9E%8B)的 `null` 引用的成員; * 用于具有錯誤可空性的 Java 互操作的泛型類型,例如一段 Java 代碼可能會向 Kotlin 的 `MutableList<String>` 中加入 `null`,這意味著應該使用 `MutableList<String?>` 來處理它; * 由外部 Java 代碼引發的其他問題。 在 Kotlin 中,類型系統區分一個引用可以容納 *null*(可空引用)還是不能容納(非空引用)。 例如,String 類型的常規變量不能容納 *null*: ```kotlin fun main() { var a: String = "abc" a = null // 編譯錯誤 } ``` 如果要允許為空,我們可以聲明一個變量為可空字符串,寫作 `String?`: ```kotlin fun main() { var b: String? = "abc" b = null // ok print(b)//null } ``` 現在,如果你調用 `a` 的方法或者訪問它的屬性,它保證不會導致 `NPE`,這樣你就可以放心地使用: ```kotlin val l = a.length ``` 但是如果你想訪問 `b` 的同一個屬性,那么這是不安全的,并且編譯器會報告一個錯誤: ```kotlin val l = b.length // 錯誤:變量“b”可能為空 ``` 但是我們還是需要訪問該屬性,對吧?有幾種方式可以做到。 ## 在條件中檢測 *null* 首先,你可以顯式檢測 `b` 是否為 *null*{: .keyword },并分別處理兩種可能: ```kotlin val l = if (b != null) b.length else -1 ``` 編譯器會跟蹤所執行檢測的信息,并允許你在 *if*{: .keyword } 內部調用 `length`。同時,也支持更復雜(更智能)的條件: ```kotlin fun main() { val b: String? = "Kotlin" if (b != null && b.length > 0) { print("String of length ${b.length}")//String of length 6 } else { print("Empty string") } } ``` 請注意,這只適用于 `b` 是不可變的情況(即在檢測和使用之間沒有修改過的局部變量,或者不可覆蓋并且有幕后字段的 *val*成員),因為否則可能會發生在檢測之后 `b` 又變為 *null*的情況。 ## 安全的調用 你的第二個選擇是安全調用操作符,寫作 `?.`: ```kotlin fun main() { val a = "Kotlin" val b: String? = null println(b?.length) println(a?.length) // 無需安全調用 } ``` 運行結果 ``` null 6 ``` 如果 `b` 非空,就返回 `b.length`,否則返回 *null*{: .keyword },這個表達式的類型是 `Int?`。 安全調用在鏈式調用中很有用。例如,如果一個員工 Bob 可能會(或者不會)分配給一個部門,并且可能有另外一個員工是該部門的負責人,那么獲取 Bob 所在部門負責人(如果有的話)的名字,我們寫作: ```kotlin bob?.department?.head?.name ``` 如果任意一個屬性(環節)為空,這個鏈式調用就會返回 *null*。 如果要只對非空值執行某個操作,安全調用操作符可以與 [`let`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/let.html) 一起使用: ```kotlin fun main() { val listWithNulls: List<String?> = listOf("Kotlin", null) for (item in listWithNulls) { item?.let { println(it) } // 輸出 Kotlin 并忽略 null } } ``` 運行結果 ``` Kotlin ``` 安全調用也可以出現在賦值的左側。這樣,如果調用鏈中的任何一個接收者為空都會跳過賦值,而右側的表達式根本不會求值: ```kotlin // 如果 `person` 或者 `person.department` 其中之一為空,都不會調用該函數: person?.department?.head = managersPool.getManager() ``` ## Elvis 操作符 當我們有一個可空的引用 `r` 時,我們可以說“如果 `r` 非空,我使用它;否則使用某個非空的值 `x`”: ```kotlin val l: Int = if (b != null) b.length else -1 ``` 除了完整的 *if*{: .keyword }-表達式,這還可以通過 Elvis 操作符表達,寫作 `?:`: ```kotlin val l = b?.length ?: -1 ``` 如果 `?:` 左側表達式非空,elvis 操作符就返回其左側表達式,否則返回右側表達式。請注意,當且僅當左側為空時,才會對右側表達式求值。 請注意,因為 *throw*和 *return*在 Kotlin 中都是表達式,所以它們也可以用在elvis 操作符右側。這可能會非常方便,例如,檢測函數參數: ```kotlin fun foo(node: Node): String? { val parent = node.getParent() ?: return null val name = node.getName() ?: throw IllegalArgumentException("name expected") // …… } ``` ## `!!` 操作符 第三種選擇是為 NPE 愛好者準備的:非空斷言運算符(`!!`)將任何值轉換為非空類型,若該值為空則拋出異常。我們可以寫 `b!!` ,這會返回一個非空的 `b` 值 (例如:在我們例子中的 `String`)或者如果 `b` 為空,就會拋出一個 `NPE` 異常: ```kotlin val l = b!!.length ``` 因此,如果你想要一個 NPE,你可以得到它,但是你必須顯式要求它,否則它不會不期而至。 ## 安全的類型轉換 如果對象不是目標類型,那么常規類型轉換可能會導致 `ClassCastException`。另一個選擇是使用安全的類型轉換,如果嘗試轉換不成功則返回 *null*: ```kotlin val aInt: Int? = a as? Int ``` ## 可空類型的集合 如果你有一個可空類型元素的集合,并且想要過濾非空元素,你可以使用 `filterNotNull` 來實現: ```kotlin val nullableList: List<Int?> = listOf(1, 2, null, 4) val intList: List<Int> = nullableList.filterNotNull() ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看