目錄
- 前言
- 代碼注釋
- 變量和常量
- 數(shù)據(jù)類型
- 操作符
- 控制流
- 異常
前言
本篇開始講解Dart語法,期間會通過對比Java、kotlin、Python、Groovy來區(qū)分語言直接的不同。
-
行尾分號
Dart中每行代碼以分號為標示,代表本行結(jié)束。和Java一樣,kotlin、groovy、Python中不需要行尾分號。
-
生產(chǎn)環(huán)境和開發(fā)環(huán)境
說下個人理解生產(chǎn)環(huán)境就是正式上線后的環(huán)境,開發(fā)環(huán)境就是開發(fā)過程中的環(huán)境。有點類似Android中的Release模式和Debug模式。
代碼注釋
-
行注釋
和java一樣,雙引號//來注釋單行代碼
-
多行注釋
Dart中使用
/* … */用來注釋一段代碼(可以是一行,也可以是多行)。-
文檔注釋
用來對一個類或者方法進行說明的注釋內(nèi)容。位于類之前或者方法之前。
可以使用 /// 開始, 也可以使用 /** 開始 并以 */ 結(jié)束
在文檔注釋中可以使用中括號[]來引用 classes、 methods、 fields、 top-level variables、 functions、 和 parameters等內(nèi)容。
變量和常量
-
變量的定義
-
var 自動類型推斷
如這種樣式:
var name = 'Bob';使用var來聲明一個變量,然后通過初始化賦值來自動進行類型推斷。 -
顯示聲明
如這種:
String name = 'Bob';和Java一樣直接聲明變量的類型。
-
-
變量的默認值
所有變量的默認值都是null。Dart中一切都是對象,即使是數(shù)字類型,也是一個對象。
示例代碼:
int lineCount; assert(lineCount == null); // 生產(chǎn)環(huán)境中asset會忽略,開發(fā)環(huán)境如果條件非true會拋異常 -
常量
在使用過程中不會被修改的變量,我們稱之為常量。Dart中的常量分為兩種:
- final:只能被賦值一次的變量。
- const:在編譯時就固定的常量。如果希望常量是類級別的,需要使用需要標記為
static const來修飾,類似java中的static。
定義和初始化方法:
final name = 'Bob'; // 自動類型推斷,此時不需要var來修飾; final String nickname = 'Bobby'; // 顯示聲明,直接執(zhí)行數(shù)據(jù)類型; const bar = 1000000; const double atm = 1.01325 * bar;
數(shù)據(jù)類型
Dart中支持的數(shù)據(jù)類型,也叫內(nèi)建類型。包含:Number、String、Boolean、List、Map、Set、Rune、Symbol。
-
Number
Number是數(shù)字類型,又細分為int和double:
- int:整數(shù)類型。取值范圍取決于平臺,DartVM上是-2^63 到 2^63 - 1之間。如果被編譯為JS,那么取值范圍就是-2^53 到 2^53 - 1。
- double:雙精度浮點類型,也就是帶小數(shù)點的數(shù)據(jù)類型。
Number類型的初始化:
var x = 1; // 默認十進制 var hex = 0xDEADBEEF; // 十六進制 var y = 1.1; // 自動推斷為double var exponents = 1.42e5; // 科學(xué)計數(shù)法 double z = 1; // 相當(dāng)于 double z = 1.0 從Dart2.1開始直接,之前的版本會報錯Number和字符串轉(zhuǎn)換
字符串轉(zhuǎn)Number,直接使用int/double中的parse函數(shù),直接傳入字符串即可
var one = int.parse('1'); // String -> int , 輸出為1 var onePointOne = double.parse('1.1'); // String -> doubleNumber轉(zhuǎn)字符串,直接使用toString()函數(shù)即可
String oneAsString = 1.toString(); // int轉(zhuǎn)字符串 String piAsString = 3.14159.toStringAsFixed(2); // 轉(zhuǎn)為字符串并只保留后兩位,輸出為3.14 -
String字符串
創(chuàng)建字符串
可以使用單引號、雙引號、三引號來定義一個字符串
單引號:使用單引號來定義一個字符串。單引號中如果需要嵌套其它引號,需要在引號前加
\來進行轉(zhuǎn)義。雙引號:和單引號類似,但雙引號中可以直接嵌套單引號,不需要轉(zhuǎn)義。
-
三引號:使用三個單引號或者三個雙引號來定義一段字符串。這種字符串可以包含多行。
var s1 = ''' You can create multi-line strings like this one. '''; var s2 = """This is also a multi-line string.""";
字符串中引用變量
字符串可以通過
${expression}的方式內(nèi)嵌表達式。 如果表達式是一個標識符,則 {} 可以省略。var s = 'string interpolation'; var result = '${s.toUpperCase()} is very handy!';原始字符串
當(dāng)我們希望整個字符串中任何轉(zhuǎn)移字符都不生效,而是要保留純文本含義,那么可以在字符前加一個r標志來表明這是一個原始字符串。類似于Python。
示例代碼:
var s = r"在Dart中使用 \n 來標示換行"; // 這里的\n并沒有直接被轉(zhuǎn)義為換行符字符串相等比較
使用
==來比較兩個字符串是否相等。字符串拼接
將多個字符串拼接為一個字符串,直接使用
+來連接兩個字符串即可。 -
Boolean布爾
有兩個值
true和false。這兩個值也是一個對象。定義一個布爾變量使用
bool -
List數(shù)組
定義方式
使用中括號
var list = [1, 2, 3];注意:只能插入同類型的元素,如果類型不一致會報錯。
讀取元素
使用下標來獲取某個元素。下標從0開始。
-
Set
一個無序不重復(fù)的序列。在Set中每個元素都是唯一的,不會出現(xiàn)重復(fù)的元素,有的話會自動刪除。類似Python中的元祖。
定義Set
使用大括號來定義
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'}; var names = <String>{};; // 定義一個空字符串Set var names = {}; // 定義一個空Set添加元素
var elements = <String>{}; elements.add('fluorine'); elements.addAll(halogens); -
Map字典
Dart中用來存放鍵值對的一種數(shù)據(jù)類型,我們稱之為Map,也就是字典。在map中一個key只能出現(xiàn)一次。當(dāng)我們從map中取元素時,如果key不存在,那么不會拋異常,但是會返回null。key可以是字符串,也可以是純數(shù)字。
Map對象的定義和初始化
Map和Set一樣,都是使用大括號來進行初始化賦值。區(qū)別就是Set存的是單個元素,而Map存的是鍵值對。
var gifts = { // Key: Value 'first': 'partridge', 'second': 'turtledoves', 'fifth': 'golden rings' // 最后一個元素后,可以帶逗號,也可以不帶 }; var gifts = Map(); gifts['first'] = 'partridge'; gifts['second'] = 'turtledoves'; gifts['fifth'] = 'golden rings'; // 使用數(shù)字作為key var nobleGases = Map(); nobleGases[2] = 'helium'; nobleGases[10] = 'neon'; nobleGases[18] = 'argon';Map對象插入值和取值
除了初始化時對map進行賦值,后續(xù)也可以直接通過key進行賦值。
var gifts = {'first': 'partridge'}; gifts['fourth'] = 'calling birds'; // 賦值 assert(gifts['first'] == 'partridge'); // 取值 Runne和Symbol,平時沒用到,用到的時候再來補充。
操作符
操作符就是兩個對象之間相互操作的一些運算操作,比如兩個整數(shù)相加。
操作符的優(yōu)先級:從左到右,從上到下。
-
算數(shù)運算符
操作符 解釋 + 相加運算, var a = 1 + 1;– 減號 , var a = 2 - 1;-expr 負號 * 乘號 / 相除,5 / 2 的結(jié)果是 2.5 ~/ 除號,但是返回值為整數(shù)。5 / 2 的結(jié)果是 2 。 % 取模,相除之后取余數(shù)。 ++var 變量自動加一。如果前面有賦值語句,那么會先加一后賦值。 var++ 變量自動加一。如果前面有賦值語句,那么會先賦值后加一。 --var 變量自動減一。如果前面有賦值語句,那么會先減一后賦值。 var-- 變量自動減一。如果前面有賦值語句,那么會先賦值后減一。 -
關(guān)系運算符
操作符 解釋 == 相等。判斷兩個對象x和y是否表示相同的事物, 使用 ==運算符。!= 不等 > 大于 < 小于 >= 大于等于 <= 小于等于 -
類型運算符
操作符 解釋 as 類型轉(zhuǎn)換。 a as b將a轉(zhuǎn)換為b;is 如果對象是指定的類型返回 True 。例如, obj is Object總是 trueis! 如果對象是指定的類型返回 False -
邏輯操作符
操作符 解釋 !表達式 對表達式結(jié)果取反(true 變?yōu)?false ,false 變?yōu)?true) || 邏輯 OR && 邏輯 AND -
條件表達式
if-else表達式的兩種種簡寫方式。 三元表達式
格式為:
condition ? 表達式1 : 表達式2如果 condition 是 true,執(zhí)行 表達式1 (并返回執(zhí)行的結(jié)果); 否則執(zhí)行 表達式2 `并返回其結(jié)果。
二元表達式
格式如下:
expr1 ?? expr2如果 expr1 是 non-null,返回其值; 否則執(zhí)行 expr2 并返回其結(jié)果。
-
級聯(lián)操作符
級聯(lián)操作符 (..) 可以在同一個對象上 連續(xù)調(diào)用多個函數(shù)以及訪問成員變量。使用級聯(lián)操作符可以避免創(chuàng)建 臨時變量, 并且寫出來的代碼看起來 更加流暢。
示例代碼
querySelector('#confirm') // 獲取對象。 ..text = 'Confirm' // 調(diào)用成員變量。 ..classes.add('important') ..onClick.listen((e) => window.alert('Confirmed!')); // 等同于下面的代碼 var button = querySelector('#confirm'); button.text = 'Confirm'; button.classes.add('important'); button.onClick.listen((e) => window.alert('Confirmed!')); // 嵌套使用級聯(lián)代碼 final addressBook = (AddressBookBuilder() ..name = 'jenny' ..email = 'jenny@example.com' ..phone = (PhoneNumberBuilder() ..number = '415-555-0100' ..label = 'home') .build()) .build();
控制流
Dart中的控制流分為如下幾種:if-else、for循環(huán)、while循環(huán)、switch、assert
-
if-else
和Java完全一樣,直接看demo即可:
if (isRaining()) { you.bringRainCoat(); } else if (isSnowing()) { you.wearJacket(); } else { car.putTopDown(); } -
for循環(huán)
標準寫法
和Java完全一樣
var message = StringBuffer('Dart is fun'); for (var i = 0; i < 5; i++) { message.write('!'); }for-in迭代寫法
var collection = [0, 1, 2]; for (var x in collection) { print(x); // 0 1 2 }迭代器對象forEach寫法
實現(xiàn)了 Iterable 接口的對象, 可以使用 forEach()方法
candidates.forEach((candidate) => candidate.interview());跳過循環(huán)
- break:結(jié)束循環(huán);
- continue:跳過本次循環(huán),開始下次循環(huán);
-
while循環(huán)
用法和Java中完全一樣
while (!isDone()) { doSomething(); } do { printLine(); } while (!atEndOfPage()); -
switch
用法和java中的用法完全一直。不過Dart中全部是使用
==來進行條件判斷的。示例代碼
var command = 'OPEN'; switch (command) { case 'CLOSED': case 'NOW_CLOSED': // 多個條件可以執(zhí)行同一個條件語句 executeClosed(); break; case 'OPEN': // 滿足open條件,執(zhí)行對應(yīng)代碼 executeOpen(); break; // case執(zhí)行結(jié)束要手動調(diào)用break代碼,否則會繼續(xù)向下執(zhí)行。 default: // 默認條件 executeUnknown(); }注意:如果沒有滿足的條件,且沒有defalut case,那么會拋異常。
-
斷言assert
通常在自動化測試和單元測試的時候會使用到斷言。在Dart中, assert 語句只在開發(fā)環(huán)境中有效, 在生產(chǎn)環(huán)境是無效的。 Flutter 中的 assert 只在debug 模式中有效。
使用方法
assert的使用方法很簡單,傳入一個條件語句:
- 如果為true就通過,程序正常運行;
- 如果不為true,正常的程序執(zhí)行流程會被中斷。
示例代碼
// 確認變量值小于100。 assert(number < 100);
異常
-
拋出異常
使用方法
throw new FormatException('Expected at least 1 section'); // 拋出一個格式異常 throw 'Out of llamas!'; // 拋出任意對象胖箭頭簡寫
因為拋出異常只有一行,所以可以使用胖箭頭來簡寫
void distanceTo(Point other) => throw UnimplementedError();-
捕獲異常 catch
示例代碼
try { breedMoreLlamas(); } on OutOfLlamasException { // 一個特殊的異常 buyMoreLlamas(); } on Exception catch (e) { // 其他任何異常 print('Unknown exception: $e'); } catch (e) { // 沒有指定的類型,處理所有異常 print('Something really unknown: $e'); }使用try-catch來嘗試捕獲異常;
使用on來判斷異常的類型;
多個異常就用多個on來判斷異常類型;
不加on則捕獲所有異常
-
函數(shù) catch() 可以帶有一個或者兩個參數(shù), 第一個參數(shù)為拋出的異常對象, 第二個為堆棧信息 (一個 StackTrace 對象)。
try { // ··· } on Exception catch (e) { print('Exception details:\n $e'); } catch (e, s) { print('Exception details:\n $e'); print('Stack trace:\n $s'); }
重新拋出異常
我們在catch完一個異常后,可能需要把這個異常再次拋出??梢允褂胷ethrow,將之前的異常重新拋出。
try { dynamic foo = true; print(foo++); // Runtime error } catch (e) { print('misbehave() partially handled ${e.runtimeType}.'); rethrow; // Allow callers to see the exception. } -
Finally
和java一樣,不管是否拋出異常, finally中的代碼都會被執(zhí)行。
- 如果
catch沒有匹配到異常, 異常會在finally執(zhí)行完成后,再次被拋出; - 如果有匹配到catch,那么會等匹配的
catch執(zhí)行完成后,再執(zhí)行finally;
try { breedMoreLlamas(); } catch (e) { print('Error: $e'); // Handle the exception first. } finally { cleanLlamaStalls(); // Then clean up. } - 如果