對於每個程序員來講,空指針異常應該是基本都會遇到過的異常,並且這個異常出現的機率還比較大。程序員
可是,空指針異常又是最容易解決的異常,由於只要加個非空判斷就能夠避免了。bash
本篇經過對比通常非空判斷和 dart 特有的語法糖告訴你如何使用 dart 進行優雅的避空。微信
通常一些簡單的 dart 測試咱們能夠直接用在線編輯器來作測試和驗證。less
下面給你們介紹的兩個都是官網的。異步
dart 在線運行器主頁版: 👇
www.dartlang.org/guides/get-…編輯器
dart 在線運行器全屏版: 👇
dartpad.dartlang.org/nullide
其中全屏版就是在主頁版裏面點擊全屏按鈕就打開了。測試
因此能夠認爲是同樣的。ui
可是筆者使用起來的不一樣以下,你們能夠根據本身的感覺選擇。this
主頁版:
優勢:運行輸出結果較全屏版快。
缺點:輸出結果區域較小,超出須要滑動查看。
全屏版:
優勢:輸出結果區域大。能夠直觀看到結果。 缺點:運行輸出結果較主頁版慢。
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**。可是直接使用**.**會直接拋出異常。
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 的語句若是加上這個會怎樣,能夠預見是不會改變的。
這邊舉例說明下使用 ?. ?? 語法糖和不使用的對比。
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 的語法糖很優雅,一行全搞定。
下面這個例子:
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');
}
複製代碼
知識學以至用纔可以鞏固。
所以這邊出了小題目給你們測試是否徹底掌握本篇內容。
答案組成了支付寶口令紅包哦~
微信公衆號回覆「牛刀小試」獲取題目。
或者直接點擊菜單欄目錄->牛刀小試獲取。
舒適提示:
若是你輸入 3 次仍是提示錯誤(錯誤過多口令紅包會暫時不可用哦),有兩種狀況。
第一種就是答案錯了。
第二種就是領取完了。
答案會在紅包領取完以後或一天以後將題目替換爲題目+答案。
由於是異步的,因此不必定實時更新哦~
更多閱讀:
Flutter 即學即用系列博客——01 環境搭建
Flutter 即學即用系列博客——02 一個純 Flutter Demo 說明
Flutter 即學即用系列博客——03 在舊有項目引入 Flutter
Flutter 即學即用系列博客——04 Flutter UI 初窺 Flutter 即學即用系列博客——05 StatelessWidget vs StatefulWidget