Dart 如何優雅的避空

前言

對於每個程序員來講,空指針異常應該是基本都會遇到過的異常,並且這個異常出現的機率還比較大。程序員

可是,空指針異常又是最容易解決的異常,由於只要加個非空判斷就能夠避免了。bash

本篇經過對比通常非空判斷和 dart 特有的語法糖告訴你如何使用 dart 進行優雅的避空。微信

目錄

1. dart 在線編輯器

通常一些簡單的 dart 測試咱們能夠直接用在線編輯器來作測試和驗證。less

下面給你們介紹的兩個都是官網的。異步

dart 在線運行器主頁版: 👇
www.dartlang.org/guides/get-…編輯器

dart 在線運行器全屏版: 👇
dartpad.dartlang.org/nullide

其中全屏版就是在主頁版裏面點擊全屏按鈕就打開了。測試

因此能夠認爲是同樣的。ui

可是筆者使用起來的不一樣以下,你們能夠根據本身的感覺選擇。this

主頁版:
優勢:運行輸出結果較全屏版快。
缺點:輸出結果區域較小,超出須要滑動查看。

全屏版:
優勢:輸出結果區域大。能夠直觀看到結果。 缺點:運行輸出結果較主頁版慢。

2. dart ?.

dart 語法糖 ?.

它的意思是左邊若是爲空返回 null,不然返回右邊的值。

A?.B
若是 A 等於 null,那麼 A?.B 爲 null
若是 A 不等於 null,那麼 A?.B 等價於 A.B

Sample:

void main() {
  Animal animal = new Animal('cat');
  Animal empty = null;
  
  //animal 非空,返回 animal.name 的值 cat
  print(animal?.name);
  //empty 爲空,返回 null
  print(empty?.name);
  
  //animal 非空,能夠直接訪問 animal.name 的值 cat
  print(animal.name);
  //empty 爲空,拋出異常
  print(empty.name);
}

class Animal {
  final String name;
  Animal(this.name);
}
複製代碼

你們拷貝代碼而後替換在線編輯器的內容,運行後會看到以下輸出:

cat
null
cat
Uncaught exception:
Cannot read property 'get$name' of null
複製代碼

能夠看到假設左邊不爲空,不論是使用**?.仍是直接用咱們熟悉的.訪問變量都是沒問題的。
可是若是左邊爲空,使用
?.會返回null**。可是直接使用**.**會直接拋出異常。

3. dart ??

dart 語法糖 ??

它的意思是左邊若是爲空返回右邊的值,不然不處理。

A??B
若是 A 等於 null,那麼 A??B 爲 B
若是 A 不等於 null,那麼 A??B 爲 A

以上面爲例子,假設咱們上面要求當 empty 爲空時,默認值輸出 unknown。

那麼能夠修改以下:

//empty 爲空,返回 null
print(empty?.name);
複製代碼

改成

//empty 爲空,原本要返回 null,因爲有 ??,返回 unknown
print(empty?.name??'unknown');
複製代碼

這樣就不會返回 null 而是返回 unknown。

一樣的你們能夠試下返回 cat 的語句若是加上這個會怎樣,能夠預見是不會改變的。

4. dart ?. ?? 優雅所在

這邊舉例說明下使用 ?. ?? 語法糖和不使用的對比。

void main() {
  C c = new C('Case 1');
  B b = new B(c);
  A a = new A(b);
  
//   C c = new C(null);
//   B b = new B(c);
//   A a = new A(b);
  
//   C c = new C('Case 2');
//   B b = null;
//   A a = new A(b);
  
  //直接使用.來最終獲取 c 的變量 value
  if (a != null && a.bMember != null && a.bMember.cMember != null) {
    print(a.bMember.cMember.value);
  } else {
    print(null);
  }
  
  //直接使用.來最終獲取 c 的變量 value,爲空時返回 unknown
  if (a != null && a.bMember != null && a.bMember.cMember != null) {
    String value = a.bMember.cMember.value;
    if (value == null) {
      value = 'unknown';
    }
    print(value);
  } else {
    print('unknown');
  }
  
  //dart 使用?.來最終獲取 c 的變量 value
  print(a?.bMember?.cMember?.value);
  //dart 使用?.來最終獲取 c 的變量 value,爲空時使用 ?? 返回 unknown
  print(a?.bMember?.cMember?.value??'unknown');
}

class A {
  final B bMember;
  A(this.bMember);
}

class B {
  final C cMember;
  B(this.cMember);
}

class C {
  final String value;
  C(this.value);
}
複製代碼

這裏面有三個 case,另外兩個 case 暫時註釋掉。

這三個 case 的結果分別爲:

Case 1
Case 1
Case 1
Case 1
複製代碼
null
unknown
null
unknown
複製代碼
null
unknown
null
unknown
複製代碼

能夠看到 dart 的語法糖很優雅,一行全搞定。

5. print 方法遇到 null

下面這個例子:

void main() {
    String a = null;
    print('exception='+a);
}
複製代碼

你以爲結果是 exception=null 嗎?

結果是

Uncaught exception:
Invalid argument: null
複製代碼

緣由是由於 print 裏面鏈接的必須是字符串。

由於這裏 a 確實是字符串,因此編輯器沒有報錯。

假設這裏 a 爲一個對象 A 的變量,會報以下提示:

The argument type 'A' can't be assigned to the parameter type 'String'. 複製代碼

那咱們怎麼處理?

有兩種方法。

方法一:

void main() {
    String a = null;
    print('exception='+'$a');
}
複製代碼

方法二:

void main() {
    String a = null??'null';
    print('exception='+a);
}
複製代碼

注意下面的寫法是不行的,緣由是 ?? 優先級沒有 + 高。須要加小括號。

void main() {
    String a = null;
    print('exception='+a??'null');
}
複製代碼

6. 牛刀小試

知識學以至用纔可以鞏固。

所以這邊出了小題目給你們測試是否徹底掌握本篇內容。

答案組成了支付寶口令紅包哦~

微信公衆號回覆「牛刀小試」獲取題目。

或者直接點擊菜單欄目錄->牛刀小試獲取。

舒適提示:
若是你輸入 3 次仍是提示錯誤(錯誤過多口令紅包會暫時不可用哦),有兩種狀況。

第一種就是答案錯了。

第二種就是領取完了。

答案會在紅包領取完以後或一天以後將題目替換爲題目+答案。

由於是異步的,因此不必定實時更新哦~

更多閱讀:
Flutter 即學即用系列博客——01 環境搭建
Flutter 即學即用系列博客——02 一個純 Flutter Demo 說明
Flutter 即學即用系列博客——03 在舊有項目引入 Flutter
Flutter 即學即用系列博客——04 Flutter UI 初窺 Flutter 即學即用系列博客——05 StatelessWidget vs StatefulWidget

相關文章
相關標籤/搜索