級別: ★☆☆☆☆
標籤:「Flutter 」「Dart」「Dart Operator」「Dart Exceptions」
作者: WYW
審校: QiShare團隊
前言
筆者在之前已經寫了2篇Dart的基礎文章了。
Dart 基礎 (一) Dart 基礎 (二)
本文是Dart基礎的第3篇,在本文中,筆者會主要介紹2部分內容,運算子和異常。
1 Operator(運算子)主要分如下4部分
- 1.1 算數運算子
- 1.2 級聯運算子
- 1.3 型別判定運算子
- 1.4 其他運算子
2 異常主要分如下4部分
- 2.0 Try
- 2.1 Throw
- 2.2 Catch
- 2.3 Finally
詳情如下:
Dart中可能遇到的運算子如下圖所示:
上述運算子中,筆者不大熟悉的運算子有:
- 算數運算子:
~/
- 賦值運算子:
??
- 級聯運算子:
..
- 型別判定運算子:
as
、is
、is!
- 其他運算子:
?.
如果你對其他運算子不大熟悉,可以檢視Dart文件。
1.1 算數運算子
~/
: 整除;
整除的結果是 運算子左側的數 除以 運算子右側的數 可以商幾。
5 ~/ 2 = 2;
7 ~/ 3 = 2;
9 ~/ 3 = 0;
複製程式碼
- 賦值運算子:
??
String qiShare1 = 'qiShare1';
String qiShare2;
qiShare2 ??= qiShare1;
print(qiShare2);
// 輸出結果
qiShare1
複製程式碼
1.2 級聯運算子
- 級聯運算子:
..
..
級聯運算子
class QiCascade {
String firstProperty;
String secondProperty;
String thirdProperty;
String fourthProperty;
}
class QiSubCascade extends QiCascade{
}
void main() {
QiCascade cascade = QiCascade();
cascade.firstProperty = 'firstPropertyValue';
cascade.secondProperty = 'secondPropertyValue';
cascade.thirdProperty = 'thirdPropertyValue';
cascade.fourthProperty = 'fourthPropertyValue';
print('輸出屬性:${cascade..firstProperty
..secondProperty
..thirdProperty
..fourthProperty}');
print('級聯輸出:');
print(cascade..firstProperty..secondProperty..thirdProperty..fourthProperty);
print('屬性:${cascade.firstProperty}');
print(cascade.firstProperty);
print(cascade.secondProperty);
print(cascade.thirdProperty);
print(cascade.fourthProperty);
cascade..firstProperty = 'changedFirstPropertyValue'
..secondProperty = 'changedSecondPropertyValue'
..thirdProperty = 'changedThirdPropertyValue'
..fourthProperty = 'changedFourthPropertyValue';
print('級聯輸出:${cascade..firstProperty
..secondProperty
..thirdProperty
..fourthProperty}');
}
複製程式碼
輸出結果
flutter: 輸出屬性:Instance of 'QiCascade'
flutter: 級聯輸出:
flutter: Instance of 'QiCascade'
flutter: 屬性:firstPropertyValue
flutter: firstPropertyValue
flutter: secondPropertyValue
flutter: thirdPropertyValue
flutter: fourthPropertyValue
flutter: 級聯輸出:Instance of 'QiCascade'
複製程式碼
看起來級聯運算子可以用於同時操作並列的例項變數。
1.3 型別判定運算子
- 型別判定運算子:
as
、is
、is!
操作符 | 解釋 |
---|---|
as | 型別轉換 |
is | 如果物件是指定的型別返回true |
is! | 如果物件是指定的型別返回false |
dynamic subCascade = QiSubCascade();
if (subCascade is QiCascade) {
subCascade.firstProperty = 'isQiCascadeFirstPropertyValue';
}
print('subCascade屬性:${subCascade.firstProperty}');
print('subCascade runtimeType:${subCascade.runtimeType}');
if(subCascade.runtimeType == QiSubCascade) {
print('subCascade的runtimeType為 ${subCascade.runtimeType}');
}
(subCascade as QiCascade).firstProperty = 'asQiCascadeFirstPropertyValue';
print('subCascade屬性:${subCascade.firstProperty}');
複製程式碼
使用 is 和 as 的區別在於:
- 使用is:如果上述subCascade不是QiCascade,則條件中的賦值程式碼不會執行
- 使用as:如果上述subCascade為null 或者不是QiCascade型別,則執行過程中會丟擲異常。
輸出結果
flutter: subCascade屬性:isQiCascadeFirstPropertyValue
flutter: subCascade runtimeType:QiSubCascade
flutter: subCascade的runtimeType為 QiSubCascade
flutter: subCascade屬性:asQiCascadeFirstPropertyValue
複製程式碼
1.4 其他運算子
運算子 | 名字 | 解釋 |
---|---|---|
() | 使用方法 | 代表呼叫一個方法。 |
[] | 訪問List | 訪問list 中特定位置的元素。 |
. | 訪問Member | 訪問元素,如上邊我們訪問cascade.firstProperty。 |
?. | 條件成員訪問 | 和 . 型別, 但是.左邊操作物件不能為null,否則丟擲異常,?.左邊的操作物件可以為null,返回null。 |
subCascade = null;
try {
print('賦值null 後訪問成員 ${subCascade.firstProperty}');
} catch (e) {
print('異常資訊 $e');
}
print('賦值null 後訪問成員 ${subCascade?.firstProperty}');
複製程式碼
輸出結果
flutter: 異常資訊 NoSuchMethodError: The getter 'firstProperty' was called on null.
Receiver: null
Tried calling: firstProperty
flutter: 賦值null 後訪問成員 null
複製程式碼
如果我們使用條件成員訪問運算子?.
。就不會有上述異常。
-
其他運算子:
?.
: 條件成員訪問,如果操作符左側的例項存在,則會取值 ;如qiShare?.name,如果qiShare 不為null,則返回結果為qiShare.name。否則返回結果為null。
subCascade = null;
subCascade ?. firstProperty;
複製程式碼
異常
常見的異常有 FormatException格式異常、HttpException網路異常、FileSystemException操作檔案的異常、越界的異常,操作的例項呼叫了沒有實現的方法 的異常。
2.1 Try
try 用於包含可能出現異常的程式碼
2.2 Throw
throw 用於丟擲異常。
2.3 Catch
Catch 用於捕獲異常,可以防止異常繼續傳遞。除非使用了rethrow
會將捕獲的異常再次丟擲。
筆者先舉了2個特定的異常例子FormatException 、IntegerDivisionByZeroException
1.FormatException,在把字串'1234B'轉為數字的時候出現的型別轉換異常。
var numValue = '1234B';
try {
int numValueInt = int.parse(numValue);
print(numValueInt);
} on FormatException catch (e){
print('出現FormatException: $e');
// rethrow; 使用rethrow 會將catch 住的異常再次丟擲
} on Exception catch(e) {
print('Exception: $e');
// rethrow; 使用rethrow 會將catch 住的異常再次丟擲
}
// 輸出結果:
/*
flutter: 出現FormatException: FormatException: Invalid radix-10 number (at character 1)
123\^]4B
*/
複製程式碼
2.IntegerDivisionByZeroException 在0作除數的時候出現的異常。整除出現。
// double zeroValue = 0.0; // 如果使用0.0 則IntegerDivisionByZeroException 不會捕獲
int zeroValue = 0;
int num1 = 1;
try {
print(num1 ~/ zeroValue); // 會觸發異常 但是也不是除0異常
// print(num1 / zeroValue); // 不會觸發異常
} on IntegerDivisionByZeroException catch(e) {
print('除以0異常:$e');
} catch (e) {
print('異常資訊:$e');
}
// 輸出結果
flutter: 除以0異常:IntegerDivisionByZeroException
複製程式碼
下邊筆者又列舉了其他的幾個異常的例子。
// 丟擲異常示例
try {
throw Exception(
'Custom Exception'
);
} catch (e) {
print(e);
}
try {
throw '自定義字串Exception';
} catch (e) {
print(e);
}
List list1 = ['QiShare'];
try {
print(list1[1]);
} catch (e) {
print(e);
}
try {
(list1 as QiCascade).firstProperty;
} catch (e) {
print(e);
}
list1 = null;
try {
print(list1[1]);
} catch (e) {
print(e);
}
try {
(list1 as QiCascade).firstProperty;
} catch (e) {
print(e);
}
複製程式碼
輸出結果
flutter: Exception: Custom Exception
flutter: 自定義字串Exception
flutter: RangeError (index): Invalid value: Only valid value is 0: 1
flutter: type 'List<dynamic>' is not a subtype of type 'QiCascade' in type cast
flutter: NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: [](1)
flutter: NoSuchMethodError: The getter 'firstProperty' was called on null.
Receiver: null
Tried calling: firstProperty
複製程式碼
針對上述程式碼的異常捕獲,筆者發現,catch不僅可以捕獲異常也可以捕獲Error,筆者Dart 的Exceptions 包括Exception 和 Error。並且對如上程式碼中RangeError、NoSuchMethodError的程式碼做了如下處理:
捕獲RangeError
List list1 = ['QiShare'];
try {
print(list1[1]);
} on RangeError catch(error) {
print('RangeError錯誤:$error');
} catch (e) {
print(e.runtimeType);
print(e);
}
// 輸出結果:
/*
flutter: RangeError錯誤:RangeError (index): Invalid value: Only valid value is 0: 1
*/
複製程式碼
捕獲NoSuchMethodError
List list1;
try {
print(list1[1]);
} on NoSuchMethodError catch(noSuchMethodError){
print('NoSuchMethodError錯誤:$noSuchMethodError');
} catch (e) {
print('異常資訊:$e');
}
// 輸出結果:
/**
* flutter: NoSuchMethodError錯誤:NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: [](1)
*/
複製程式碼
2.4 Finally
Finally 部分的程式碼,不管是否有出現異常,都會執行,如果出現了異常,則執行完catch中的程式碼後,會執行Finally 中的程式碼,如果沒有出現異常,則執行完了try中的程式碼後,會執行Finally 中的程式碼。
List list1;
try {
print(list1[1]);
} on NoSuchMethodError catch(noSuchMethodError){
print('NoSuchMethodError錯誤:$noSuchMethodError');
} catch (e) {
print('異常資訊:$e');
} finally {
print('執行Finally 中的程式碼');
}
/**
* flutter: NoSuchMethodError錯誤:NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: [](1)
flutter: 執行Finally 中的程式碼
*/
複製程式碼
還有一種情況是try 中的程式碼出現了異常,但是沒有使用catch 進行異常捕獲。但使用了finally 語句。像這種情況,出現異常的情況下,會先執行finally 中的程式碼,然後丟擲異常。 程式碼如下:
List list3;
try {
print(list3[1]);
} finally {
print('執行Finally 中的程式碼');
}
// 輸出結果:
/**
flutter: 執行Finally 中的程式碼
flutter: ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
flutter: The following NoSuchMethodError was thrown while handling a gesture:
flutter: The method '[]' was called on null.
flutter: Receiver: null
flutter: Tried calling: [](1)
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
省略............
*/
複製程式碼
參考學習網址
小編微信:可加並拉入《QiShare技術交流群》。
關注我們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公眾號)
推薦文章:
Dart基礎(一)
Dart基礎(二)
iOS 簡訊驗證碼倒數計時按鈕
iOS 環境變數配置
iOS 中處理定時任務的常用方法
演算法小專欄:貪心演算法
iOS 快速實現分頁介面的搭建
iOS 中的介面旋轉
奇舞週刊