Dart2中流程控制語句以及異常
if and else
Dart支持 if 語句,else 語句是可選的,例如:
if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}
不同於JavaScript,這裏的條件必須是boolean值,不能是其他的任何值。
for循環
你可以使用標準的 for 循環來做遍歷:
var message = StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
message.write('!');
}
Dart2中 for 循環裏面的閉包可以捕獲索引的值。例如:
var callbacks = [];
for (var i = 0; i < 2; i++) {
callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
此段代碼先輸出 0 ,再輸出 1 ,正是我們期望的結果。然而,這個例子在JavaScript中的輸出爲:先輸出 2 ,再輸出 2.
如果循環的對象是一個可迭代的對象,你可以使用 forEach() 方法。如果你不需要知道當前迭代的計數器,使用 forEach() 是一個很好的選擇。
candidates.forEach((candidate) => candidate.interview());
想List和Set這樣的可迭代類也支持 for-in 這種形式的迭代方式:
var collection = [0, 1, 2];
for (var x in collection) {
print(x); // 0 1 2
}
While 和 do-while循環
一個 while 循環在循環之前計算表達式的值:
while (!isDone()) {
doSomething();
}
一個 do-while 再循環開始之後計算表達式的值:
do {
printLine();
} while (!atEndOfPage());
break 和 continue
使用 break 來停止循環:
while (true) {
if (shutDownRequested()) break;
processIncomingRequests();
}
使用 continue 來跳到下一個循環:
for (int i = 0; i < candidates.length; i++) {
var candidate = candidates[i];
if (candidate.yearsExperience < 5) {
continue;
}
candidate.interview();
}
如果你使用Iterable(如列表List和集合Set),則可以使用如下方式實現上面的例子:
candidates
.where((c) => c.yearsExperience >= 5)
.forEach((c) => c.interview());
Switch 和 case
Dart中的Switch 語句使用 == 來比較 整型、字符串或者編譯時常量。參與比較的對象必須全部是同一種類的實例(不能是該類的任意子類型的實例),並且該類不能覆寫 == .在switch 語句中可以使用枚舉類型。
每一個不爲空的 case 語句都以一個 break 語句結尾,也可以以 continue ,rethrow,throw,或者return 作爲結尾。
一下示例省略了case子句中的break語句,從而產生錯誤:
var command = 'OPEN';
switch (command) {
case 'OPEN':
executeOpen();
// ERROR: Missing break
case 'CLOSED':
executeClosed();
break;
}
然而,Dart支持空的 case 子句,例如:
var command = 'CLOSED';
switch (command) {
case 'CLOSED': // Empty case falls through.
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
也可以使用一個 continue 語句和一個標籤實現如下功能:
var command = 'CLOSED';
switch (command) {
case 'CLOSED':
executeClosed();
continue nowClosed;
// Continues executing at the nowClosed label.
nowClosed:
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
一個 case 子句可以有本地變量,這些變量的可見性僅僅在該子句的範圍內。
Assert
如果一個 boolean 條件爲 false 則使用一個 assert 語句來中斷正常執行:
// Make sure the variable has a non-null value.
assert(text != null);
// Make sure the value is less than 100.
assert(number < 100);
// Make sure this is an https URL.
assert(urlString.startsWith('https'));
注意:Assert語句對生產環境的代碼沒有影響,它們僅僅作用在開發環境中。Flutter在調試模式(debug mode)纔會啓用 assert。僅限開發時使用的工具如 dartdevc 通常默認支持 assert。一些工具,例如 dart 和 dart2js,通過命令行標誌 –enable-asserts 來支持 assert 。
要關聯一個消息給 assert,添加一個字符串作爲第二個參數即可:
assert(urlString.startsWith('https'),
'URL ($urlString) should start with "https".');
當沒有 case 子句匹配時,使用 default 子句來執行代碼。
var command = 'OPEN';
switch (command) {
case 'CLOSED':
executeClosed();
break;
case 'PENDING':
executePending();
break;
case 'APPROVED':
executeApproved();
break;
case 'DENIED':
executeDenied();
break;
case 'OPEN':
executeOpen();
break;
default:
executeUnknown();
}
異常
你的Dart代碼可以拋出或者捕獲異常。異常是一種錯誤,用來指示發生了一些意外事件。如果一個異常沒有被捕獲,通常程序將會被終止。
與Java不同,所有的Dart異常都是未檢查異常(unchecked exception)。方法不會聲明它們可能拋出哪些異常,所以你也不需要捕獲任何異常。
Dart提供異常(Exception)和錯誤(Error)類型,以及許多預定義的子類型。當然你也可以定義你自己的異常。然而,Dart程序可以拋出任意非null對象,不僅是異常和錯誤。
拋出異常
下面的例子就是拋出一個異常:
throw FormatException('Expected at least 1 section');
你也可以拋出任意對象:
throw 'Out of llamas!';
注意:生產質量的代碼通常會拋出實現 Exception 或者 Error 的類型。
捕獲異常
捕獲異常可以停止異常的傳播(除非你重新拋出異常),捕獲異常給了你一個處理它的機會:
breedMoreLlamas();
} on OutOfLlamasException {
buyMoreLlamas();
}
處理可能拋出多種異常的代碼,你可以指定多個 catch 子句。第一個與拋出異常的類型相匹配的catch子句會處理該異常。如果catch子句沒有指定類型,那麼該catch可以處理任意類型的異常:
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}
如前面的例子所示,你可以使用 on 或者 catch 也可以二者都用。當你需要指定異常的類型時使用 on 。當你的異常處理需要使用到異常對象時使用 catch 。
你可以給 catch() 指定一個或者兩個參數。第一個參數代表拋出的異常,第二個參數是執行的堆棧路徑(一個 StackTrace 對象)。
try {
// ···
} on Exception catch (e) {
print('Exception details:\n $e');
} catch (e, s) {
print('Exception details:\n $e');
print('Stack trace:\n $s');
}
要部分處理異常,使異常繼續傳播,使用 rethrow 關鍵字。
void misbehave() {
try {
dynamic foo = true;
print(foo++); // Runtime error
} catch (e) {
print('misbehave() partially handled ${e.runtimeType}.');
rethrow; // Allow callers to see the exception.
}
}
void main() {
try {
misbehave();
} catch (e) {
print('main() finished handling ${e.runtimeType}.');
}
}
Finally
爲了保證一些代碼不管異常是否拋出都要執行,使用一個 finally 子句。如果沒有 catch 子句與異常相匹配,那麼這個異常會在 finally 子句執行完成之後繼續傳播。
try {
breedMoreLlamas();
} finally {
// Always clean up, even if an exception is thrown.
cleanLlamaStalls();
}
finally 子句在任意匹配的 catch 子句之後執行。
try {
breedMoreLlamas();
} catch (e) {
print('Error: $e'); // Handle the exception first.
} finally {
cleanLlamaStalls(); // Then clean up.
}