版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。http://www.itdecent.cn/p/3d927a7bf020
轉(zhuǎn)載請(qǐng)標(biāo)明出處:
http://www.itdecent.cn/p/3d927a7bf020
本文出自 AWeiLoveAndroid的博客
Flutter系列博文鏈接 ↓:
工具安裝:
Flutter基礎(chǔ)篇:
- 谷歌Flutter1.0正式版發(fā)布
- Flutter基礎(chǔ)篇(1)-- 跨平臺(tái)開發(fā)框架和工具集錦
- Flutter基礎(chǔ)篇(2)-- 老司機(jī)用一篇博客帶你快速熟悉Dart語(yǔ)法
- Flutter基礎(chǔ)篇(3)-- Flutter基礎(chǔ)全面詳解
- Flutter基礎(chǔ)篇(4)-- Flutter填坑全面總結(jié)
- Flutter基礎(chǔ)篇(5)-- Flutter代碼模板,解放雙手,提高開發(fā)效率必備
- Flutter基礎(chǔ)篇(6)-- 水平和垂直布局詳解
- Flutter基礎(chǔ)篇(7)-- Flutter更新錯(cuò)誤全面解決方案(圖文+視頻講解)
- Flutter基礎(chǔ)篇(8)-- Flutter for Web詳細(xì)介紹
- Flutter基礎(chǔ)篇(9)-- 手把手教你用Flutter實(shí)現(xiàn)Web頁(yè)面編寫
- Flutter1.9升級(jí)體驗(yàn)總結(jié)(Flutter Web 1.9最新版本填坑指南)
Flutter進(jìn)階篇:
- Flutter進(jìn)階篇(1)-- 手把手帶你快速上手調(diào)試Flutter項(xiàng)目
- Flutter進(jìn)階篇(2)-- Flutter路由詳解
- Flutter進(jìn)階篇(3)-- Flutter 的手勢(shì)(GestureDetector)分析詳解
- Flutter進(jìn)階篇(4)-- Flutter的Future異步詳解
- Flutter進(jìn)階篇(5)-- 使用Flutter創(chuàng)建插件詳解并發(fā)布到Pub庫(kù)
- Flutter進(jìn)階篇(6)-- PageStorageKey、PageStorageBucket和PageStorage使用詳解
- Flutter進(jìn)階篇(7)-- Flutter路由輕量級(jí)框架FRouter
Dart語(yǔ)法系列博文鏈接 ↓:
Dart語(yǔ)法基礎(chǔ)篇:
Dart語(yǔ)法進(jìn)階篇:
【前言】Dart語(yǔ)言是使用flutter框架開發(fā)時(shí)候必備的語(yǔ)言,flutter是一個(gè)跨平臺(tái)的框架,一套代碼就可以完美實(shí)現(xiàn)安卓和ios兩個(gè)平臺(tái),適配也很不錯(cuò),Dart語(yǔ)言很友好,和java很類似,學(xué)習(xí)成本也是很低的。所以這也是我推薦學(xué)習(xí)Dart語(yǔ)言的一個(gè)原因。
從本篇文章開始講解Dart語(yǔ)言的基本使用,我將會(huì)連續(xù)推出好幾篇文章詳解,希望幫助大家快速掌握Dart語(yǔ)言。
本文目錄:
一、注釋
二、關(guān)鍵字(56個(gè))
三、變量和常量
四、特殊數(shù)據(jù)類型
五、運(yùn)算符
六、控制流程語(yǔ)句
七、異常
本文代碼同步發(fā)布在Github:
https://github.com/AweiLoveAndroid/Flutter-learning/tree/master/projects/dart_demo
怎么運(yùn)行代碼?
如果你使用IDEA或者Android Studio:
打開IDEA或者Android Studio,新建一個(gè)Flutter項(xiàng)目,然后在test目錄運(yùn)行我的代碼;或者里面去寫你自己的
dart文件,然后右鍵run就可以運(yùn)行了。(注意:需要連接手機(jī)或者模擬器)。
如果你使用vscode:
打開vscode,執(zhí)行菜單欄
運(yùn)行,就可以了(確保只有一個(gè)dart文件,免得運(yùn)行的文件不是你想要的,就很尷尬了,vscode也可以設(shè)置默認(rèn)運(yùn)行的文件是哪個(gè),但是新手不建議去設(shè)置,很麻煩。因?yàn)槟銈兿胱羁斓倪\(yùn)行效果,所有建議只有一個(gè)dart文件是最好的)。
一、注釋
Dart的注釋分為3種:?jiǎn)涡凶⑨?、多行注釋、文檔注釋。
1、單行注釋以
//開頭。Dart編譯器會(huì)忽略//和行尾之間的所有內(nèi)容。
例如:// todo:待完成
2、多行注釋以
/*開頭,以*/結(jié)尾。介于/*和*/兩者之間的內(nèi)容會(huì)被編譯器忽略(除非該注釋是一個(gè)文檔注釋)。多行注釋可以嵌套。
例如:/* todo:待完成 */
3、文檔注釋以
///或者/**開頭。可以通過(guò)dartdoc命令導(dǎo)出文檔。
文檔注釋的使用,例如:/// todo:待完成
文檔的導(dǎo)出如圖所示:

導(dǎo)出的結(jié)果在我的工程根路徑的/doc/api/文件夾里面,如圖所示:

然后瀏覽器打開index.html就可以看到文檔了。如圖所示:

二、關(guān)鍵字(60個(gè))
5個(gè)上下文關(guān)鍵字(僅在特定位置具有含義。它們?cè)谌魏蔚胤蕉际怯行У臉?biāo)識(shí)符)
| 關(guān)鍵字 | - | - | - |
|---|---|---|---|
| async | hide | on | show |
| sync | - | - | - |
其中內(nèi)置標(biāo)志符有:(20個(gè))
| 關(guān)鍵字 | - | - | - |
|---|---|---|---|
| abstract | as | covariant | defered |
| dynamic | export | external | factory |
| Function | get | implements | import |
| interface | library | mixin | operator |
| part | set | static | typedef |
Dart新增的,有限的保留字,支持異步功能的關(guān)鍵字有:(2個(gè))
| 關(guān)鍵字 | - | - | - |
|---|---|---|---|
| await | yield |
33個(gè)保留字(不能使用保留字作為標(biāo)識(shí)符)
| 關(guān)鍵字 | - | - | - |
|---|---|---|---|
| assert | break | case | catch |
| class | const | continue | default |
| do | else | enum | extends |
| false | final | finally | for |
| if | in | is | new |
| null | rethrow | return | super |
| switch | this | throw | true |
| try | var | void | while |
| with | - | - | - |
跟java相比,Dart特有的關(guān)鍵字有:(27個(gè))
| 關(guān)鍵字 | - | - | - |
|---|---|---|---|
| as | async | await | covariant |
| deferred | dynamic | export | external |
| factory | Function | get | hide |
| in | is | library | mixin |
| on | operator | part | rethrow |
| set | show | sync | typedef |
| var | with | yield |
三、變量和常量
(一)變量的聲明,可以使用 var、Object 或 dynamic 關(guān)鍵字。
創(chuàng)建變量并初始化變量實(shí)例:
var name = '張三' ;
變量存儲(chǔ)引用。
- 使用Object或dynamic關(guān)鍵字
dynamic name = '張三';
調(diào)用的變量name包含對(duì)String值為“張三” 的對(duì)象的引用。
name推斷變量的類型是String,但可以通過(guò)指定它來(lái)更改該類型。
如果對(duì)象不限于單一類型(沒(méi)有明確的類型),請(qǐng)使用Object或dynamic關(guān)鍵字
Object name = '張三';
dynamic name = '李四';
- 顯式聲明將被推斷的類型
比如String,int等。
//可以使用String顯示聲明字符串類型
String name = '張三' ; //代替var name = '張三';
這個(gè)類型有很多,具體在下文有介紹。
(二)默認(rèn)值
未初始化的變量的初始值為null(包括數(shù)字),因此數(shù)字、字符串都可以調(diào)用各種方法。
//測(cè)試 數(shù)字類型的初始值是什么?
int intDefaultValue;
// assert 是語(yǔ)言內(nèi)置的斷言函數(shù),僅在檢查模式下有效
// 在開發(fā)過(guò)程中, 除非條件為真,否則會(huì)引發(fā)異常。(斷言失敗則程序立刻終止)
assert(intDefaultValue == null);
print(intDefaultValue);//打印結(jié)果為null,證明數(shù)字類型初始化值是null
(三)Final 和 Const的用法
如果您從未打算更改一個(gè)變量,那么使用 final 或 const,不是var,也不是一個(gè)類型。
一個(gè) final 變量只能被設(shè)置一次;const 變量是一個(gè)編譯時(shí)常量。(Const變量是隱式的final。)
final的頂級(jí)或類變量在第一次使用時(shí)被初始化。
- 1、被final或者const修飾的變量,變量類型可以省略。
//可以省略String這個(gè)類型聲明
final name1 = "張三";
//final String name1 = "張三";
const name2 = "李四";
//const String name2 = "李四";
- 2、被 final 或 const 修飾的變量無(wú)法再去修改其值。
final name1 = "張三";
// 這樣寫,編譯器提示:a final variable, can only be set once
// 一個(gè)final變量,只能被設(shè)置一次。
//name1 = "zhangsan";
const name2 = "李四";
// 這樣寫,編譯器提示:Constant variables can't be assigned a value
// const常量不能賦值
// name2 = "lisi";
- 3、注意:flnal 或者 const 不能和 var 同時(shí)使用
//這樣寫都會(huì)報(bào)錯(cuò)
//final var name1 = "張三";
//const var name2 = "李四";
- 4、常量如果是類級(jí)別的,請(qǐng)使用 static const
static const speed = 100;
- 5、常量的運(yùn)算
const speed = 100; //速度(km/h)
const double distance = 2.5 * speed; // 距離 = 速度 * 時(shí)間
final speed2 = 100; //速度(km/h)
final double distance2 = 2.5 * speed2; // 距離 = 速度 * 時(shí)間
- 6、const關(guān)鍵字不只是聲明常數(shù)變量。您也可以使用它來(lái)創(chuàng)建常量值,以及聲明創(chuàng)建常量值的構(gòu)造函數(shù)。 任何變量都可以有一個(gè)常量值。
// 注意: [] 創(chuàng)建的是一個(gè)空的list集合
// const []創(chuàng)建一個(gè)空的、不可變的列表(EIL)。
var varList = const []; // varList 當(dāng)前是一個(gè)EIL
final finalList = const []; // finalList一直是EIL
const constList = const []; // constList 是一個(gè)編譯時(shí)常量的EIL
// 可以更改非final,非const變量的值
// 即使它曾經(jīng)具有const值
varList = ["haha"];
// 不能更改final變量或const變量的值
// 這樣寫,編譯器提示:a final variable, can only be set once
// finalList = ["haha"];
// 這樣寫,編譯器提示:Constant variables can't be assigned a value
// constList = ["haha"];
- 7、只要任何插值表達(dá)式是一個(gè)計(jì)算結(jié)果為null或數(shù)字,字符串或布爾值的編譯時(shí)常量,那么文字字符串就是編譯時(shí)常量。(關(guān)于$表達(dá)式和不同的數(shù)據(jù)類型后面會(huì)講解。)
// 這些是常量字符串
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';
// 這些不是常量字符串
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = const [1, 2, 3];
const validConstString = '$aConstNum $aConstBool $aConstString';
//這樣用就會(huì)報(bào)錯(cuò):Const variables must be initialized with a constant value
// const常量必須用conat類型的值初始化。
// const invalidConstString = '$aNum $aBool $aString $aConstList';
四、特殊數(shù)據(jù)類型
Dart支持以下特殊類型:
numbers 數(shù)字
strings 字符串
booleans 布爾
lists list集合(也稱為數(shù)組)
maps map集合
runes 字符(用于在字符串中表示Unicode字符)
(一)num數(shù)字類型
num是數(shù)字類型的父類,有兩個(gè)子類 int 和 double。
num類型包括基本的運(yùn)算符,如+,-,/和*,位運(yùn)算符,如>>,在int類中定義。如果num和它的子類沒(méi)有你要找的東西,math庫(kù)可能會(huì)找到。比如你會(huì)發(fā)現(xiàn)abs(),ceil()和floor()等方法。
(1)int類型
int表示整數(shù),int默認(rèn)是64位二進(jìn)制補(bǔ)碼整數(shù),int的取值不大于64位,具體取決于平臺(tái)。編譯為JavaScript時(shí),整數(shù)僅限于valus,可以用雙精度浮點(diǎn)值精確表示。可用的整數(shù)值包括-253和253之間的所有整數(shù),以及一些幅度較大的整數(shù)。這包括一些大于2^63的整數(shù)。 因此,在編譯為JavaScript的Dart VM和Dart代碼之間,int類中的運(yùn)算符和方法的行為有時(shí)會(huì)有所不同。例如,當(dāng)編譯為JavaScript時(shí),按位運(yùn)算符將其操作數(shù)截?cái)酁?2位整數(shù)。
示例如下:
int intNum1 = 10 ;
print(intNum1);//結(jié)果是10
int intNum2 = 0xDEADBEEF ;
print(intNum2);//結(jié)果是3735928559
判斷一個(gè)int值需要多少bit(位),可以使用bitLength,例如:
// bitLength 返回存儲(chǔ)此int整數(shù)所需的最小位數(shù)
int a1 = 1; // 占了1個(gè)bit 相當(dāng)于二進(jìn)制數(shù)字 00000000 00000001
int a2 = 12; // 占了4個(gè)bit 相當(dāng)于二進(jìn)制數(shù)字 00000000 00001100
int a3 = 123; // 占了7個(gè)bit 相當(dāng)于二進(jìn)制數(shù)字 00000000 01111011
int a4 = 1234; // 占了11個(gè)bit 相當(dāng)于二進(jìn)制數(shù)字 00000100 11010010
print('${a1.bitLength}'); // 1
print('${a2.bitLength}'); // 4
print('${a3.bitLength}'); // 7
print('${a4.bitLength}'); // 11
(2)double類型
Dart的double是IEEE 754標(biāo)準(zhǔn)中規(guī)定的64位浮點(diǎn)數(shù)。double的最大值是:1.7976931348623157e+308,double類里面有一個(gè)常量maxFinite,我們通過(guò)語(yǔ)句print(double. maxFinite)可以得到double的最大值。
如果一個(gè)數(shù)字包含一個(gè)小數(shù),那么它就是一個(gè)double類型。示例如下:
double doubleNum1 = 1.1;
print(doubleNum1); //結(jié)果是1.1
double doubleNum2 = 1.42e5;
print(doubleNum2); //結(jié)果是142000.0
(3)Dart2.1里面新增特性,當(dāng)double的值為int值時(shí),int自動(dòng)轉(zhuǎn)成double。
例如:double test = 12;//打印結(jié)果是12.0
(4)Dart2.1,int也有api轉(zhuǎn)成double。
例如:
int test = 10;
print(test.toDouble()); // 結(jié)果是: 10.0
(5)Dart2.1,double也有api轉(zhuǎn)成int,會(huì)把小數(shù)點(diǎn)后面的全部去掉。
例如:
double test2 = 15.1;
double test3 = 15.1234;
print(test2.toInt());// 結(jié)果是15
print(test3.toInt());// 結(jié)果是15
(二)String字符串類型
Dart里面的String是一系列 UTF-16代碼單元。
(1)您可以使用單引號(hào)或雙引號(hào)來(lái)創(chuàng)建一個(gè)字符串。
String str1 = '單引號(hào)基本使用demo.';
String str2 = "雙引號(hào)基本使用demo.";
(2)單引號(hào)或者雙引號(hào)里面嵌套使用引號(hào)。
單引號(hào)里面嵌套單引號(hào),或者//雙引號(hào)里面嵌套雙引號(hào),必須在前面加反斜杠。
// 單引號(hào)里面有單引號(hào),必須在前面加反斜杠
String str3 = '單引號(hào)里面有單引號(hào)it\'s,必須在前面加反斜杠.';
//雙引號(hào)里面嵌套單引號(hào)(正常使用)
String str4 = "雙引號(hào)里面有單引號(hào)it's.";
//單引號(hào)里面嵌套雙引號(hào)(正常使用)
String str5 = '單引號(hào)里面有雙引號(hào),"hello world"';
//雙引號(hào)里面嵌套雙引號(hào),必須在前面加反斜杠
String str6 = "雙引號(hào)里面有雙引號(hào),\"hello world\"";
print(str3);// 雙引號(hào)里面有單引號(hào)it's,必須在前面加反斜杠
print(str4);// 雙引號(hào)里面有單引號(hào)it's.
print(str5);// 單引號(hào)里面有雙引號(hào),hello world"
print(str6);//雙引號(hào)里面有雙引號(hào),"hello world"
(3)多個(gè)字符串相鄰中間的空格問(wèn)題:
除了單引號(hào)嵌套單引號(hào)或者雙引號(hào)嵌套雙引號(hào)不允許出現(xiàn)空串之外,其余的幾種情況都是可以運(yùn)行的。
示例如下:
這個(gè)會(huì)報(bào)錯(cuò)
//String blankStr1 = 'hello''''world';
//這兩個(gè)運(yùn)行正常
String blankStr2 = 'hello'' ''world'; //結(jié)果: hello world
String blankStr3 = 'hello''_''world'; //結(jié)果: hello_world
// 這個(gè)會(huì)報(bào)錯(cuò)
//String blankStr4 = "hello""""world";
這兩個(gè)運(yùn)行正常
String blankStr5 = "hello"" ""world"; //結(jié)果: hello world
String blankStr6 = "hello""_""world"; //結(jié)果: hello_world
單引號(hào)里面有雙引號(hào),混合使用運(yùn)行正常
String blankStr7 = 'hello""""world'; //結(jié)果: hello""""world
String blankStr8 = 'hello"" ""world'; //結(jié)果: hello"" ""world
String blankStr9 = 'hello""_""world'; //結(jié)果: hello""_""world
雙引號(hào)里面有單引號(hào),混合使用運(yùn)行正常
String blankStr10 = "hello''''world"; //結(jié)果: hello''''world
String blankStr11 = "hello'' ''world"; //結(jié)果: hello'' ''world
String blankStr12 = "hello''_''world"; //結(jié)果: hello''_''world
(4)您可以使用相鄰字符串文字或+ 運(yùn)算符連接字符串:
- 直接把相鄰字符串寫在一起,就可以連接字符串了。
String connectionStr1 = '字符串連接''甚至可以在''換行的時(shí)候進(jìn)行。';
print(connectionStr1);// 字符串連接甚至可以在換行的時(shí)候進(jìn)行。
- 用+把相鄰字符串連接起來(lái)。
String connectionStr2 = '字符串連接'+ '甚至可以在'+ '換行的時(shí)候進(jìn)行。';
print(connectionStr2);// 字符串連接甚至可以在換行的時(shí)候進(jìn)行。
- 使用單引號(hào)或雙引號(hào)的三引號(hào):
String connectionStr3 = '''
這是用單引號(hào)創(chuàng)建的
多行字符串。
''' ;
print(connectionStr3);
String connectionStr4 = """這是用雙引號(hào)創(chuàng)建的
多行字符串。""";
print(connectionStr4);
print(connectionStr3)輸出結(jié)果如下:
這是用單引號(hào)創(chuàng)建的
多行字符串。
print(connectionStr4)的輸出結(jié)果如下:
這是用雙引號(hào)創(chuàng)建的
多行字符串。
(5)關(guān)于轉(zhuǎn)義符號(hào)的使用
聲明raw字符串(前綴為r),在字符串前加字符r,或者在\前面再加一個(gè)\,
可以避免“\”的轉(zhuǎn)義作用,在正則表達(dá)式里特別有用。
舉例如下:
print(r"換行符:\n"); //這個(gè)結(jié)果是 換行符:\n
print("換行符:\\n"); //這個(gè)結(jié)果是 換行符:\n
print("換行符:\n"); //這個(gè)結(jié)果是 換行符:
(6)使用$可以獲得字符串中的內(nèi)容,使用${表達(dá)式}也可以將表達(dá)式的值放入字符串中。使用${表達(dá)式}時(shí)可以使用字符串拼接,也可以使用String類或者Object里面的某些方法獲得相關(guān)字符串屬性。
1、使用
$+字符串
var height = 48.0;
print('當(dāng)前標(biāo)題的高度是$height'); //當(dāng)前標(biāo)題的高度是48.0
2、使用$+字符串,以及字符串拼接
String name = "張三";
print("$name"+"是我們的部門經(jīng)理"); // 張三是我們的部門經(jīng)理
3、這里使用了字符串的拼接,以及使用了String類里面的toUpperCase()函數(shù),把字母全部變成大寫。
String replaceStr = 'Android Studio';
assert('你知道' +
'${replaceStr.toUpperCase()}'
+ '最新版本是多少嗎?' ==
'你知道ANDROID STUDIO最新版本是多少嗎?');
注:==操作符測(cè)試兩個(gè)對(duì)象是否相等。assert是斷言,如果條件為true,繼續(xù)進(jìn)行,否則拋出異常,中端操作。
(三)bool布爾類型
Dart表示布爾值的類型叫做bool,它有兩個(gè)值,分別是:true和false,它們都是編譯時(shí)常量。
Dart使用的是顯式的檢查值,檢查值的類型,如下所示:
// 檢查是否為空字符串
var emptyStr = '';
assert(emptyStr.isEmpty);
// 檢查是否小于等于0
var numberStr = 0;
assert(numberStr <= 0);
// 檢查是否為null
var nullStr;
assert(nullStr == null);
// 檢查是否為NaN
var value = 0 / 0;
assert(value.isNaN);
assert 是Dart語(yǔ)言里的的斷言函數(shù),僅在Debug模式下有效。
在開發(fā)過(guò)程中, 除非條件為真,否則會(huì)引發(fā)異常。(斷言失敗則程序立刻終止)。
(四)list集合,也成為數(shù)組
在Dart中,數(shù)組是List對(duì)象,因此大多數(shù)人只是將它們稱為L(zhǎng)ist。
以下是一個(gè)簡(jiǎn)單的Dart的List:
創(chuàng)建一個(gè)int類型的list
List list = [10, 7, 23];
print(list);// 輸出結(jié)果 [10, 7, 23]
要?jiǎng)?chuàng)建一個(gè)編譯時(shí)常量const的list,示例如下:
List constantList = const[10,3,15];
print(constantList);// 輸出結(jié)果 [10, 3, 15]
注意事項(xiàng):
1.可以直接打印list包括list的元素,list也是一個(gè)對(duì)象。但是java必須遍歷才能打印list,java若直接打印list,結(jié)果是地址值。
2.和java一樣list里面的元素必須保持類型一致,不一致就會(huì)報(bào)錯(cuò)。
3.和java一樣list的角標(biāo)從0開始。
Dart的list集合給我們提供了很多api,示例如下,api太多就不逐個(gè)展示了:
| 操作 | 代碼 | 含義 | 輸出結(jié)果 |
|---|---|---|---|
| 新增 | list.add(1);print(list); | 把數(shù)字1添加到list中,默認(rèn)是添加到末尾 | [10, 7, 23, 1] |
| 移除 | list.remove(1);print(list); | 移除數(shù)字1 | [10, 7, 23] |
| 插入 | list.insert(0, 5);print(list); | 在索引為0的地方插入數(shù)字5 | [5, 10, 7, 23] |
| 查找某個(gè)索引的值 | int value = list.indexOf(10);print(value); | 查找10在list中的索引 | 1 |
| 判斷元素是否包含 | bool result = list.contains(5);print(result); | 查找list中是否包含數(shù)字5 | true |
(五)map集合
Dart中的map是將鍵和值相關(guān)聯(lián)的對(duì)象。鍵和值都可以是任何類型的對(duì)象。每個(gè)鍵只出現(xiàn)一次,但您可以多次使用相同的值。
(1)創(chuàng)建方式:
- 直接聲明,用{}表示,里面寫key和value,每組鍵值對(duì)中間用逗號(hào)隔開。
Map companys = {'first': '阿里巴巴', 'second': '騰訊', 'fifth': '百度'};
print(companys);//打印結(jié)果 {first: 阿里巴巴, second: 騰訊, fifth: 百度}
- 先聲明,再去賦值。
Map companys1 = new Map();
companys1['first'] = '阿里巴巴';
companys1['second'] = '騰訊';
companys1['fifth'] = '百度';
print(companys1);
//打印結(jié)果 {first: 阿里巴巴, second: 騰訊, fifth: 百度}
- 要?jiǎng)?chuàng)建一個(gè)編譯時(shí)常量const的map,請(qǐng)?jiān)趍ap文字之前添加const:
final fruitConstantMap = const {2: 'apple',10: 'orange',18: 'banana'};
// 打印結(jié)果{second: 騰訊, fifth: 百度, 5: 華為}
(2)添加元素。格式: 變量名[key] = value,其中key可以是不同類型。
//添加一個(gè)新的元素,key為“5”,value為“華為”
companys[5] = '華為';
print(companys);//打印結(jié)果 {first: 阿里巴巴, second: 騰訊, fifth: 百度, 5: 華為}
(3)修改元素。格式:變量名[key] = value
例如:把key為first的元素對(duì)應(yīng)的value改成 alibaba
companys['first'] = 'alibaba';
print(companys);//打印結(jié)果 {first: alibaba, second: 騰訊, fifth: 百度, 5: 華為}
(4)查詢?cè)?/h5>
bool mapKey = companys.containsKey('second');
bool mapValue = companys.containsValue('百度');
print(mapKey); //結(jié)果為:true
print(mapValue); //結(jié)果為:true
(5)刪除元素.可以使用map的remove或者clear方法。
companys.remove('first');// 移除key為“first”的元素。
print(companys);// 打印結(jié)果{second: 騰訊, fifth: 百度, 5: 華為}
companys.clear();// 清空map集合的數(shù)據(jù)。
print(companys);// 打印結(jié)果{}
(6)關(guān)于map集合的小結(jié):
1.創(chuàng)建map有兩種方式。
2.map的key類型不一致也不會(huì)報(bào)錯(cuò)。
3.添加元素的時(shí)候,會(huì)按照你添加元素的順序逐個(gè)加入到map里面,哪怕你的key不連續(xù)。
比如key分別是 1,2,4,看起來(lái)有間隔,事實(shí)上添加到map的時(shí)候{1:value,2:value,4:value} 這種形式。
4.添加的元素的key如果是map里面某個(gè)key的英文,照樣可以添加到map里面,
比如可以為3和key為three可以同時(shí)存在。
5.map里面的key不能相同,但是value可以相同,value可以為空字符串或者為null。
(六)runes 字符(用于在字符串中表示Unicode字符)
bool mapKey = companys.containsKey('second');
bool mapValue = companys.containsValue('百度');
print(mapKey); //結(jié)果為:true
print(mapValue); //結(jié)果為:true
companys.remove('first');// 移除key為“first”的元素。
print(companys);// 打印結(jié)果{second: 騰訊, fifth: 百度, 5: 華為}
companys.clear();// 清空map集合的數(shù)據(jù)。
print(companys);// 打印結(jié)果{}
1.創(chuàng)建map有兩種方式。
2.map的key類型不一致也不會(huì)報(bào)錯(cuò)。
3.添加元素的時(shí)候,會(huì)按照你添加元素的順序逐個(gè)加入到map里面,哪怕你的key不連續(xù)。
比如key分別是 1,2,4,看起來(lái)有間隔,事實(shí)上添加到map的時(shí)候{1:value,2:value,4:value} 這種形式。
4.添加的元素的key如果是map里面某個(gè)key的英文,照樣可以添加到map里面,
比如可以為3和key為three可以同時(shí)存在。
5.map里面的key不能相同,但是value可以相同,value可以為空字符串或者為null。
Unicode為世界上所有的書寫系統(tǒng)中使用的每個(gè)字母,數(shù)字和符號(hào)定義了唯一的數(shù)值。
Dart字符串是UTF-16代碼單元的序列,所以在字符串中表達(dá)32位Unicode值需要特殊的語(yǔ)法。
Unicode代碼點(diǎn)的常用方法是\uXXXX,其中XXXX是一個(gè)4位十六進(jìn)制值。
例如,心形字符()是\u2665。要指定多于或少于4個(gè)十六進(jìn)制數(shù)字,請(qǐng)將該值放在大括號(hào)中。 例如,笑的表情符號(hào)是\u{1f600}。
String類有幾個(gè)屬性可以用來(lái)提取符文信息。 codeUnitAt和codeUnit屬性返回16位代碼單元。
以下示例說(shuō)明了符文,16位代碼單元和32位代碼點(diǎn)之間的關(guān)系。
var clapping = '\u{1f44f}';
print(clapping);
print(clapping.codeUnits);
print(clapping.runes.toList());
//使用String. fromCharCodes顯示字符圖形
Runes input = new Runes(
'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(new String.fromCharCodes(input));
五、運(yùn)算符
運(yùn)算符在每一種語(yǔ)言中都很常見,Dart的運(yùn)算符如下表所示:

我這里不詳細(xì)去講解每個(gè)運(yùn)算符的用法,我這里主要講一下Dart里面比較有代表性的以及有特點(diǎn)的一些運(yùn)算符相關(guān)用法。
(一)?.像.一樣,但最左邊的操作數(shù)可以為空。
比如:Test?.funs從表達(dá)式Test中選擇屬性funs,除非Test為空(當(dāng)Test為空時(shí),Test?.funs的值為空)。
class Test {
static int funs = 5;
Test() {
print('構(gòu)造函數(shù) Test');
}
static fun() {
print('Test fun函數(shù)');
}
}
void main(){
print(Test?.funs); // 打印5
}
(二)..級(jí)聯(lián)符號(hào)..
級(jí)聯(lián)符號(hào)..允許您在同一個(gè)對(duì)象上進(jìn)行一系列操作。 除了函數(shù)調(diào)用之外,還可以訪問(wèn)同一對(duì)象上的字段。其實(shí)相當(dāng)于java的鏈?zhǔn)秸{(diào)用。
例如:
String s = (new StringBuffer()
..write('test1 ')
..write('test2 ')
..write('test3 ')
..write('test4 ')
..write('test5'))
.toString();
print(s); // test1 test2 test3 test4 test5
(三)?? 三目運(yùn)算符的一種形式。
expr1 ?? expr2 表示如果expr1非空,則返回其值; 否則返回expr2的值。
//普通三元運(yùn)算符
int a = 10;
var values = a > 5 ? a : 0;
//??操作符
print('a ??=3 : ${a ??= 3}'); // 3
(四)~/ 除法,返回一個(gè)整數(shù)結(jié)果,其實(shí)就是取商。
小學(xué)都學(xué)過(guò):被除數(shù) ÷ 除數(shù) = 商 ... 余數(shù),在Dart里面A ~/ B = C,這個(gè)C就是商,這個(gè)語(yǔ)句相當(dāng)于Java里面的A / B = C。Dart與java不同的是,Dart里面如果使用A / B = D語(yǔ)句,這個(gè)結(jié)果計(jì)算出來(lái)的是真實(shí)的結(jié)果。示例如下:
var result1 = 15/7;
print(result1); // 結(jié)果是:2.142857...
var result2 = 15~/7;
print(result2); // 結(jié)果是:2
順便提一下取模操作,在Dart里面A % B = E,這個(gè)E就是余數(shù),%符號(hào)表示取模,例如:
var result3 = 15%7;
print(result3); // 結(jié)果是:1
(五)as、is與is!
as 判斷屬于某種類型
is 如果對(duì)象具有指定的類型,則為true
is! 如果對(duì)象具有指定的類型,則為false
例如:
class Test {
static int funs = 5;
Test() {
print('構(gòu)造函數(shù) Test');
}
static fun() {
print('Test fun函數(shù)');
}
}
class Test2 extends Test {
Test2() {
print('構(gòu)造函數(shù) Test2');
}
void fun() {
print('Test2 fun函數(shù)');
}
}
void main(){
print(test2 is Test); // true
print(test is! Test2); // true
(test2 as Test2).fun(); // Test2 fun函數(shù)
// 相當(dāng)于
// if (test2 is Test) {
// test2.fun();
// }
六、控制流程語(yǔ)句
控制流程語(yǔ)句和Java語(yǔ)言差不多,有這些語(yǔ)句:
(一)if else
if(條件語(yǔ)句){
內(nèi)容體
}else{
內(nèi)容體
}
(二)for循環(huán)
1.簡(jiǎn)單for循環(huán)
for(初始值;判斷條件;循環(huán)后的語(yǔ)句){
內(nèi)容體
}
例如:
for(int i=0;i<10;i++){
print(i);
}
也可以通過(guò)for循環(huán)內(nèi)部的閉包獲取索引的值。
var array = [];
for(var i=0;i<10;i++){
array.add(()=> print(i));
}
2.使用foreach循環(huán),一般List和Set都可以使用foreach遍歷元素。
如果要迭代的對(duì)象是Iterable,或者你不想知道當(dāng)前的迭代次數(shù),可以使用foreach()方法。
var numbers = [1,2,3,4,5,6,7,8,9];
numbers.foreach((number)=> print(number));
3.使用for in循環(huán),一般List和Set使用for-in遍歷元素。
var list = [1,2,3];
for(var data in list){
print(data);
}
4.Dart的for循環(huán)里面可以使用標(biāo)記:(比較有特色的地方)
Dart的標(biāo)記:標(biāo)記是后面跟著冒號(hào)的標(biāo)識(shí)符。帶標(biāo)記的陳述是以標(biāo)記 L為前綴的陳述。帶標(biāo)簽的case子句是標(biāo)簽L前綴的switch語(yǔ)句中的case子句。標(biāo)簽的唯一作用是為“break”和“continue”聲明提供對(duì)象。
大多數(shù)此功能與其他語(yǔ)言類似,因此以下大部分內(nèi)容可能對(duì)讀者來(lái)說(shuō)都很熟悉。Dart的switch聲明中處理continue是比較獨(dú)特的,所以這一部分需要一點(diǎn)時(shí)間去閱讀和熟悉。
- 1.循環(huán)(Loops)
標(biāo)簽最常用作break 和 continue內(nèi)部循環(huán)。假設(shè)你有嵌套的循環(huán),并要跳轉(zhuǎn)到break或continue到外部循環(huán)。如果沒(méi)有標(biāo)記,這不可能(輕松)實(shí)現(xiàn)。
以下示例使用continue 標(biāo)記名稱從內(nèi)部循環(huán)直接跳轉(zhuǎn)到外部循環(huán)的下一輪循環(huán):
// 返回具有最小總和的內(nèi)部列表(正整數(shù))。
/// Returns the inner list (of positive integers) with the smallest sum.
List<int> smallestSumList(List<List<int>> lists) {
var smallestSum = 0xFFFFFFFF; //已知list的總和較小。
var smallestList = null;
outer: // 這就是標(biāo)記
for (var innerList in lists) {
var sum = 0;
for (var element in innerList) {
assert(element >= 0);
sum += element;
// 無(wú)需繼續(xù)迭代內(nèi)部列表。它的總和已經(jīng)太高了。
if (sum > smallestSum) continue outer; // continue 跳出到標(biāo)記處(outer)
}
smallestSum = sum;
smallestList = innerList;
}
return smallestList;
}
此函數(shù)在所有l(wèi)ist中運(yùn)行,但只要總和過(guò)高,就會(huì)停止累加變量。
同理,可以使用break跳出到外部循環(huán):
// 計(jì)算第一個(gè)非空l(shuí)ist
List<int> firstListWithNullValueList(List<List<int>> lists) {
var firstListWithNullValues = null;
outer:
for (var innerList in lists) {
for (var element in innerList) {
if (element == null) {
firstListWithNullValues = innerList;
break outer; // break 返回到標(biāo)記處
}
}
}
// 現(xiàn)在繼續(xù)正常的工作流程
if (firstListWithNullValues != null) {
// ...
}
return firstListWithNullValues;
}
- 2.跳出代碼塊
標(biāo)記也可以用于跳出代碼塊。假設(shè)我們想要統(tǒng)一處理錯(cuò)誤條件,但有多個(gè)條件(可能是深度嵌套)來(lái)揭示(reveal)錯(cuò)誤。標(biāo)簽可以幫助構(gòu)建此代碼。
void doSomethingWithA(A a) {
errorChecks: {
if (a.hasEntries) {
for (var entry in a.entries) {
if (entry is Bad) break errorChecks; // 跳出代碼塊
}
}
if (a.hasB) {
var b = new A.b();
if (b.inSomeBadState()) break errorChecks; // 跳出代碼塊
}
// 一些看起來(lái)都正常
use(a);
return;
}
// 錯(cuò)誤的情況,執(zhí)行這里的代碼:
print("something bad happened");
}
class A{
bool hasEntries = false;
bool hasB = true;
List<Bad> entries = [new Bad2(),new Bad2()];
A.b(){
}
bool inSomeBadState(){
return false;
}
}
void use(A a){}
abstract class Bad{}
class Bad1 extends Bad{}
class Bad2 extends Bad{}
對(duì)代碼塊的使用break指令,使得Dart繼續(xù)執(zhí)行塊之后的語(yǔ)句。從某個(gè)角度來(lái)看,它是一個(gè)結(jié)構(gòu)化的goto,它只允許跳轉(zhuǎn)到當(dāng)前指令之后的嵌套較少的位置。
雖然聲明標(biāo)簽在代碼塊中最有用,但它們可以用在在每個(gè)語(yǔ)句中。
例如,foo: break foo;是一個(gè)有效的聲明。
請(qǐng)注意:continue上面的循環(huán)可以通過(guò)將循環(huán)體包裝到帶標(biāo)記的代碼塊中并使用break來(lái)實(shí)現(xiàn)。
也就是說(shuō),以下兩個(gè)循環(huán)是等效的:
//以下兩種描述是等價(jià)的:
// 使用 continue
for (int i = 0; i < 10; i++) {
if (i.isEven) continue;
print(i);
}
// 使用 break.
for (int i = 0; i < 10; i++) {
labels: {
// isEven 當(dāng)且僅當(dāng)該整數(shù)為偶數(shù)時(shí)才返回true
if (i.isEven) break labels;
print(i);
}
}
- 3.Switch中的標(biāo)記(label)
標(biāo)記也可以用于switch內(nèi)部。
Switch中的標(biāo)記允許continue 使用其它的case 子句。在最簡(jiǎn)單的形式中,這可以作為一種方式來(lái)實(shí)現(xiàn)下一個(gè)子句:
void switchExample(int foo) {
switch (foo) {
case 0:
print("foo is 0");
break;
case 1:
print("foo is 1");
continue shared; // Continue使用在被標(biāo)記為shared的子句中
shared:
case 2:
print("foo is either 1 or 2");
break;
}
}
有趣的是, Dart沒(méi)有要求continue的目標(biāo)子句是當(dāng)前case子句之后的子句。
帶標(biāo)記的任何case子句都是有效的目標(biāo)。這意味著,Dart的switch語(yǔ)句實(shí)際上是狀態(tài)機(jī)(state machines)。
以下示例演示了這種濫用,其中整個(gè)switch實(shí)際上只是用作狀態(tài)機(jī)(state machines)。
void main() {
runDog();
}
void runDog() {
int age = 0;
int hungry = 0;
int tired = 0;
bool seesSquirrel() => new Random().nextDouble() < 0.1;
bool seesMailman() => new Random().nextDouble() < 0.1;
switch (1) {
start:
case 0:
print("dog 方法已經(jīng)開始");
print('case 0 ==> age: $age');
print('case 0 ==> hungry: $hungry');
print('case 0 ==> tired: $tired');
continue doDogThings;
sleep:
case 1:
print("sleeping");
tired = 0;
age++;
if (age > 20) break;
print('case 1 ==> age: $age');
print('case 1 ==> hungry: $hungry');
print('case 1 ==> tired: $tired');
continue doDogThings;
doDogThings:
case 2:
if (hungry > 2) continue eat;
if (tired > 3) continue sleep;
if (seesSquirrel()) continue chase;
if (seesMailman()) continue bark;
print('case 2 ==> age: $age');
print('case 2 ==> hungry: $hungry');
print('case 2 ==> tired: $tired');
continue play;
chase:
case 3:
print("chasing");
hungry++;
tired++;
print('case 3 ==> age: $age');
print('case 3 ==> hungry: $hungry');
print('case 3 ==> tired: $tired');
continue doDogThings;
eat:
case 4:
print("eating");
hungry = 0;
print('case 4 ==> age: $age');
print('case 4 ==> hungry: $hungry');
print('case 4 ==> tired: $tired');
continue doDogThings;
bark:
case 5:
print("barking");
tired++;
print('case 5 ==> age: $age');
print('case 5 ==> hungry: $hungry');
print('case 5 ==> tired: $tired');
continue doDogThings;
play:
case 6:
print("playing");
tired++;
hungry++;
print('case 6 ==> age: $age');
print('case 6 ==> hungry: $hungry');
print('case 6 ==> tired: $tired');
continue doDogThings;
}
}
這個(gè)函數(shù)從一個(gè)switch子句跳到另一個(gè)子句,模擬了狗的生命。
在Dart中,標(biāo)簽只允許在case子句中使用,因此我必須添加一些case永遠(yuǎn)不會(huì)到達(dá)的行。
這個(gè)功能很酷,但很少使用。由于我們的編譯器增加了復(fù)雜性,我們經(jīng)常討論它的刪除。到目前為止,它已經(jīng)在我們的審查中幸存下來(lái),但我們最終可能會(huì)簡(jiǎn)化我們的規(guī)范并讓用戶自己添加一個(gè)while(true)循環(huán)(帶有標(biāo)記)。這個(gè)dog的示例可以重寫如下:
var state = 0;
loop:
while (true)
switch (state) {
case 0:
print("dog has started");
state = 2; continue;
case 1: // sleep.
print("sleeping");
tired = 0;
age++;
// The inevitable... :(
if (age > 20) break loop; // 跳出循環(huán)
// Wake up and do dog things.
state = 2; continue;
case 2: // doDogThings.
if (hungry > 2) { state = 4; continue; }
if (tired > 3) { state = 1; continue; }
if (seesSquirrel()) { state = 3; continue; }
...
如果狀態(tài)值被命名為常量,那么它將與原始版本一樣具有可讀性,但不需要switch語(yǔ)句來(lái)支持狀態(tài)機(jī)。
(三)while 和do while
while(判斷條件){
內(nèi)容體
}
do{
內(nèi)容體
} while(判斷條件);
while(a>5){
print(a);
}
do{
print(a);
} while(a>5);
(四)break continue
break 停止循環(huán)
while(a>5){
if(b>5){
print(a);
break;
}
}
continue 跳到下一個(gè)循環(huán)
while(a>5){
if(b<10){
print(b);
continue;
}
}
如果使用Iterable(list或者set),則可以使用下面這種方式:
// 第一個(gè)是滿足條件就進(jìn)入 第二個(gè)是foreach遍歷
arrays
.when((c)=>c.counts >=5)
.foreach((c)=>c.next());
(五)switch case
比較integer, string,編譯時(shí)常量 使用==。比較對(duì)象必須是同一個(gè)類的實(shí)例(不是其子類的實(shí)例),并且該類不能重寫==。枚舉類型在switch也可以運(yùn)行。
每一條非空case字子句以break結(jié)束,也可以使用其他的方式結(jié)束:continue,throw或者return。
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();
}
(六)assert
如果布爾條件為false,則使用assert語(yǔ)句來(lái)中斷正常執(zhí)行。例如:
// 確保變量具有非空值
assert(text != null);
// 確保值小于100
assert(number < 100);
// 確保這是一個(gè) https 網(wǎng)址
assert(urlString.startsWith('https'));
要將消息附加到斷言,請(qǐng)?zhí)砑右粋€(gè)字符串作為第二個(gè)參數(shù)。
assert(urlString.startsWith('https'),'URL ($urlString) should start with "https".');
上例中assert的第一個(gè)參數(shù)可以是任何解析為布爾值的表達(dá)式。如果表達(dá)式的值為true,則斷言成功并繼續(xù)執(zhí)行。如果為false,則斷言失敗并拋出異常
七、異常
Dart代碼可以拋出并捕獲異常。Exception是指示發(fā)生意外事件的錯(cuò)誤。如果未捕獲異常,則會(huì)暫停引發(fā)異常的isolate ,并且通常會(huì)終止isolate及其程序。
與Java相比,Dart的所有異常都是未經(jīng)檢查的異常。方法不會(huì)聲明它們可能引發(fā)的異常,并且您不需要捕獲任何異常。
Dart提供了Exception和Error 類型,以及許多預(yù)定義的子類型。當(dāng)然,您可以定義自己的Exception。但是,Dart程序可以拋出任何非null對(duì)象,作為Exception(不僅僅是Exception和Error對(duì)象)。
(一)throw
以下是拋出或引發(fā)異常的示例:
throw FormatException('Expected at least 1 section');
你也可以拋出任意對(duì)象,例如:throw '格式不正確!';
通常在開發(fā)中會(huì)拋出Error或者Exception類型。
因?yàn)閽伋霎惓J且粋€(gè)表達(dá)式,所以可以在=>語(yǔ)句中以及允許表達(dá)式的任何其他地方拋出異常:
void distanceTo(Point other) => throw UnimplementedError();
(二)try catch
捕獲或捕獲異常會(huì)阻止異常傳遞(除非您重新拋出異常)。捕獲異常使您有機(jī)會(huì)處理它:
try {
breedMoreLlamas();
} on OutOfLlamasException {
buyMoreLlamas();
}
要處理可能拋出多種類型異常的代碼,可以指定多個(gè)catch子句。與拋出對(duì)象的類型匹配的第一個(gè)catch子句處理異常。如果catch子句未指定類型,則該子句可以處理任何類型的拋出對(duì)象。
您可以使用on或catch或兩者兼而有之。使用on時(shí)需要指定異常類型。使用catch時(shí),你的異常處理程序需要異常對(duì)象。
示例:
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');
}
您可以指定一個(gè)或兩個(gè)參數(shù)catch()。第一個(gè)是拋出的異常,第二個(gè)是堆棧跟蹤(StackTrace對(duì)象)。
示例:
try {
// ···
} on Exception catch (e) {
print('Exception details:\n $e');
} catch (e, s) {
print('Exception details:\n $e');
print('Stack trace:\n $s');
}
要部分處理異常,同時(shí)允許它傳遞,請(qǐng)使用rethrow關(guān)鍵字。
示例:
void misbehave() {
try {
dynamic foo = true;
print(foo++); // 運(yùn)行時(shí)異常
} catch (e) {
print('misbehave() partially handled ${e.runtimeType}.');
rethrow; // 允許調(diào)用者查看exception.
}
}
void main() {
try {
misbehave();
} catch (e) {
print('main() finished handling ${e.runtimeType}.');
}
}
(三)finally
無(wú)論是否拋出異常,要確保某些代碼運(yùn)行,請(qǐng)使用finally子句。如果沒(méi)有catch子句匹配該異常,則在finally子句運(yùn)行后傳遞異常。
示例:
try {
breedMoreLlamas();
} finally {
// 即使拋出異常 也會(huì)執(zhí)行這句代碼.
cleanLlamaStalls();
}
該finally子句在任何匹配的catch子句之后運(yùn)行:
try {
breedMoreLlamas();
} catch (e) {
// 首先會(huì)處理異常
print('Error: $e');
} finally {
// 然后執(zhí)行這句語(yǔ)句
cleanLlamaStalls();
}