按照慣例燃观,先來(lái)個(gè) Hello World ??
void main() {
print('Hello World');
}
一褒脯、變量與常量
1.1.變量
- 沒(méi)有初始化的變量默認(rèn)值為
null
,基本數(shù)據(jù)類型未初始化也是null
(Dart 中甚至連 數(shù)字缆毁、方法和null
都是對(duì)象)番川。
int a;
double b;
String s;
Object c;
dynamic d;
var e;
print(a); // null
print(b); // null
print(s); // null
print(c); // null
print(d); // null
print(e); // null
- 可選的類型:如果變量沒(méi)有明確的類型,可以使用
Object
或dynamic
關(guān)鍵字积锅。
dynamic a = 5;
dynamic b = 5.6;
dynamic c = 'sss';
var d = 5;
var e = 5.6;
var f = 'sss';
- 在聲明變量的時(shí)候爽彤,可以選擇加上具體類型,這樣可以更加清晰的表達(dá)你的意圖缚陷。 IDE 編譯器等工具有可以使用類型來(lái)更好的幫助你适篙, 可以提供代碼補(bǔ)全、提前發(fā)現(xiàn) bug 等功能箫爷。
int a = 5;
double b = 4.1;
String s = 'sss';
List list = [56,3,4,6,0];
Map map = {
'key1':'value1',
'key2':'value2'
};
注意:在 Dart 中有兩種表示所有對(duì)象的類型:Object 和 dynamic嚷节。但是表達(dá)的意義不同:
Object 類型說(shuō)明:可以接受任意對(duì)象,只需要這個(gè)對(duì)象定義了 Object 所定義的函數(shù) 即可虎锚。
dynamic 類型說(shuō)明:沒(méi)有一個(gè)類型可以表達(dá)你所期望的對(duì)象硫痰。 (有可能有類型可以表達(dá),但是你不在乎窜护。)
如下示例:
// 接受任意對(duì)象.
void log(Object object) {
print(object.toString());
}
// 僅接受 bool 或者 String 類型, 它們不能在類型注解中表示效斑。
bool convertToBool(arg) { // dynamic arg,默認(rèn) dynamic 類型,可省略
if (arg is bool) return arg;
if (arg is String) return arg == 'true';
throw new ArgumentError('Cannot convert $arg to a bool.');
}
1.2.final and const
- 如果以后不打算修改一個(gè)變量柱徙,可以使用
final
或者const
,被final
或者const
修飾的變量在第一次聲明時(shí)必須初始化缓屠,否則編譯器報(bào)錯(cuò)。
// 報(bào)錯(cuò):The final variable 's1' must be initialized.
final String s1;
// 報(bào)錯(cuò):The const variable 's2' must be initialized.
const String s2;
- 被
final
或者const
修飾的變量护侮、對(duì)象實(shí)例一旦初始化敌完,就不能再次賦值,否則編譯器報(bào)錯(cuò)羊初。
final String s1 = 'ss';
// 報(bào)錯(cuò):s1,a final variable ,can only be set once.
s1 = 'bb';
const String s2 = 'ss';
// 報(bào)錯(cuò):Constant variables cant't be assigned a value.
s2 = 'ff';
- 實(shí)例變量可以被
final
修飾但是不能被const
修飾滨溉,否則編譯器報(bào)錯(cuò)。
class Person {
}
class Son {
final Person p1 = Person();
// 報(bào)錯(cuò):Only static field can be declared as const.
const Person p2 = Person();
}
-
final
或者const
不能和var
同時(shí)使用长赞,否則編譯器報(bào)錯(cuò)晦攒。
// 報(bào)錯(cuò):Members can't be declared to be both 'const' and 'var'
const var String s1 = 'Tim';
// 報(bào)錯(cuò):Members can't be declared to be both 'final' and 'var'
final var String s2 = 'Tim';
- 被
final
或者const
修飾的變量,變量類型可以省略得哆,建議指定數(shù)據(jù)類型勤家。
const a = 'Tim';
const b = 4;
const c = 4.5;
final d = 'Tim';
final e = 4;
final f = 4.5;
-
const
變量為編譯時(shí)常量。 如果const
變量在類中柳恐,請(qǐng)定義為static const
伐脖。 可以直接定義const
和其值,也 可以定義一個(gè)const
變量使用其他const
變量的值來(lái)初始化其值乐设。
class Son {
static const String name1 = 'Tom';
// 報(bào)錯(cuò): Only static fields can be declared as const
const String name4 = 'Tom';
void test() {
const String name2 = 'Tom';
const bar = 1000000;
const atm = 1.01325 * bar;
// 報(bào)錯(cuò):Cant't have modifier 'static' here.
static const String name3 = 'Tom';
}
}
-
const
關(guān)鍵字不僅僅只用來(lái)定義常量讼庇。 有可以用來(lái)創(chuàng)建不變的值, 還能定義構(gòu)造函數(shù)為const
類型的近尚,這種類型 的構(gòu)造函數(shù)創(chuàng)建的對(duì)象是不可改變的蠕啄。任何變量都可以有一個(gè)不變的值。 但是const
常量必須用const類型的值初始化戈锻,否則編譯器報(bào)錯(cuò)歼跟。
void test() {
var foo = const []; // foo is currently an EIA.
final bar = const []; // bar will always be an EIA.
const baz = const []; // baz is a compile-time constant EIA.
const bar1 = 1000000;
final atm1 = 1.01325 * bar1;
final bar2 = 1000000;
// 報(bào)錯(cuò):Constant variables must be initialized with a constant value.
const atm2 = 1.01325 * bar2;
}
- 一個(gè)
const
變量是編譯時(shí)常量。 (Const
變量同時(shí)也是final
變量格遭。) 頂級(jí)的final
變量或者類中的final
變量在 第一次使用的時(shí)候初始化哈街。
二、num
Dart 支持兩種類型的數(shù)字:
-
int
整數(shù)值拒迅,其取值通常位于 -253 和 253 之間骚秦。 -
double
64-bit (雙精度) 浮點(diǎn)數(shù),符合 IEEE 754 標(biāo)準(zhǔn)璧微。
int
和 double
都是 num
的子類作箍。 num
類型定義了基本的操作符,例如 +
, -
, /
, 和*
前硫, 還定義了 abs()
胞得、ceil()
、和 floor()
等 函數(shù)屹电。 (位操作符阶剑,例如>>
定義在 int
類中。) 如果num
或者其子類型不滿足你的要求嗤详,請(qǐng)參考 dart:math 庫(kù)个扰,這些都是各種語(yǔ)言相同的套路,不多說(shuō)葱色。
var x = 1;
var hex = 0xDEADBEEF;
var bigInt = 9223372036854775807;
var y = 1.1;
var exponents = 1.42e5;
int x2 = 2;
double x3 = 6;
print('x = $x'); // x = 1
print(hex); // 3735928559
print(bigInt); // 9223372036854775807
print(y); // 1.1
print(exponents); // 142000.0
print(x2); // 2
print(x3); // 6.0
三递宅、bool
Dart 是強(qiáng)
bool
類型檢查,只有bool
類型的值是true
才被認(rèn)為是true
苍狰,否則false
办龄。這點(diǎn)和某些語(yǔ)言不一樣, 像 1淋昭、 "aString"俐填、 以及 someObject 等值都被認(rèn)為是 false(應(yīng)該是Dart version 2.0之前的版本)。在Dart version 2.0以后版本(本文Dart version 2.1.2)翔忽,如果數(shù)據(jù)類型不是
bool
類型值卻進(jìn)行了條件判斷英融,Dart Analysis則會(huì)報(bào)錯(cuò)盏檐。boo
類型的值是true
和false
都是編譯時(shí)常量。assert
是Dart語(yǔ)言內(nèi)置的斷言函數(shù)驶悟,僅在檢查模式下有效
在開(kāi)發(fā)過(guò)程中,除非條件為真胡野,否則會(huì)引發(fā)異常。(斷言失敗則程序立刻終止)痕鳍。
四、String
- Dart 字符串是 UTF-16 編碼的字符序列笼呆。 可以使用單引號(hào)或者雙引號(hào)來(lái)創(chuàng)建字符串熊响。
var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
// 單引號(hào)中有單引號(hào)需要加轉(zhuǎn)義字符
var s3 = 'It\'s easy to escape the string delimiter.';
/// 雙引號(hào)中有單引號(hào)不需要加轉(zhuǎn)義字符
var s4 = "It's even easier to use the other delimiter.";
// 單引號(hào)中使用雙引號(hào)
var s5 = '分為可"區(qū)分"情況分';
- 使用三個(gè)單引號(hào)或者雙引號(hào)也可以創(chuàng)建多行字符串對(duì)象:
var s6 = '''
You can create
multi-line strings like this one.
''';
var s7 = """This is also a
multi-line string.""";
- 可以在字符串中使用表達(dá)式,規(guī)則:
${expression}
诗赌。如果表達(dá)式是一個(gè)對(duì)象(在Dart中變量也是對(duì)象)汗茄,可以省略{}
, Dart 會(huì)調(diào)用對(duì)象的toString()
函數(shù)來(lái)獲取一個(gè)字符串境肾。若表達(dá)式不是對(duì)象表達(dá)式不可省略剔难!
var s8 = 'hello';
var s9 = '$s8 world';
print(s9); // hello world
var s10 = '${s8.toUpperCase()} WORLD';
print(s10); // HELLO WORLD
// {} 不可省略
var s11 = '$s8.toUpperCase() WORLD';
print(s11); // hello.toUpperCase() WORLD
- 一個(gè)帶有r 前綴可以創(chuàng)建一個(gè) “原始 raw” 字符串:
var s12 = r"In a raw string, even \n isn't special.";
print(s12); // In a raw string, even \n isn't special.
- 字符串字面量是編譯時(shí)常量, 帶有字符串插值的字符串定義奥喻,若干插值表達(dá)式引用的為編譯時(shí)常量則其結(jié)果也是編譯時(shí)常量偶宫。
// These work in a const string.
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';
// These do NOT work in a const string.
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = const [1, 2, 3];
const validConstString1 = '$aConstNum $aConstBool $aConstString';
print(validConstString1); // 0 true a constant string
// 報(bào)錯(cuò):Const variables must be initialized with a constant value.
const validConstString2 = '$aNum $aBool $aString $aConstList';
var validConstString3 = '$aNum $aBool $aString $aConstList';
print(validConstString3);// 0 true a string [1, 2, 3]
- 字符串的拼接
String s1 = 'hello';
String s2 = 'world';
// 官方不推薦
String s3 = s1 + s2;
// 官方推薦
String s4 = '$s1$s2';
print(s3); // helloworld
print(s4); // helloworld
五、List
array (或者有序集合)是所有編程語(yǔ)言中最常見(jiàn)的集合類型环鲤。 在 Dart 中數(shù)組就是 List 對(duì)象纯趋。所以 通常我們都稱之為 lists。Dart list 字面量和 JavaScript 的數(shù)組字面量類似冷离。
lis
t里面的元素必須保持類型一致吵冒,不一致就會(huì)報(bào)錯(cuò)。list的角標(biāo)從0開(kāi)始
list
里面有多個(gè)相同的元素“X”, 調(diào)用list
對(duì)象的remove()
方法只會(huì)刪除集合中第一個(gè)該元素西剥。在java中必須遍歷才能打印
list
痹栖,直接打印是地址值。Dart語(yǔ)言可以直接打印list
包括list
的元素瞭空。在
list
字面量之前添加const
關(guān)鍵字揪阿,可以 定義一個(gè)不變的list
對(duì)象(編譯時(shí)常量)。
//創(chuàng)建一個(gè)int類型的list
List list = [10, 7, 23];
// 輸出[10, 7, 23]
print(list);
// 使用List的構(gòu)造函數(shù)咆畏,也可以添加int參數(shù)南捂,表示List固定長(zhǎng)度,不能進(jìn)行添加 刪除操作
var fruits = new List();
// 添加元素
fruits.add('apples');
// 添加多個(gè)元素
fruits.addAll(['oranges', 'bananas']);
List subFruits = ['apples', 'oranges', 'banans'];
// 添加多個(gè)元素
fruits.addAll(subFruits);
// 輸出: [apples, oranges, bananas, apples, oranges, banans]
print(fruits);
/*
獲取List的長(zhǎng)度,判斷List是否為空時(shí)最好不要用lenth屬性旧找,
用isEmpty或者isNotEmpty溺健,可以提高性能
*/
print(fruits.length);
// 判斷List是否為空
bool isEmpty = fruits.isEmpty;
bool isNotEmpty = fruits.isNotEmpty;
// 獲取第一個(gè)元素
print(fruits.first);
// 獲取元素最后一個(gè)元素
print(fruits.last);
// 利用索引獲取元素
print(fruits[0]);
// 查找某個(gè)元素的索引號(hào)
print(fruits.indexOf('apples'));
// 刪除指定位置的元素,返回刪除的元素
print(fruits.removeAt(0));
// 刪除指定元素,成功返回true钮蛛,失敗返回false
// 如果集合里面有多個(gè)“apples”, 只會(huì)刪除集合中第一個(gè)該元素
fruits.remove('apples');
// 刪除最后一個(gè)元素鞭缭,返回刪除的元素
fruits.removeLast();
// 刪除指定范圍(索引)元素剖膳,含頭不含尾
fruits.removeRange(start,end);
// 刪除指定條件的元素(這里是元素長(zhǎng)度大于6)
fruits.removeWhere((item) => item.length >6);
// 刪除所有的元素
fruits.clear();
/*
在 `list` 字面量之前添加 `const` 關(guān)鍵字,
可以 定義一個(gè)不變的 `list` 對(duì)象(編譯時(shí)常量)
*/
var constantList = const [1, 2, 3];
- 排序岭辣。
排序一個(gè) list 可以使用 sort()
函數(shù)潮秘。還可以提供一個(gè)用來(lái)排序 的比較方法。排序方法返回值 為:對(duì)于小的值 為 < 0易结;對(duì)于相同的值為 0 ;對(duì)于大的值為 > 0柜候。 下面的示例使用由 Comparable 定義的 compareTo()
函數(shù)搞动,該函數(shù)也被 String 實(shí)現(xiàn)了。
var fruits = ['bananas', 'apples', 'oranges'];
// Sort a list.
/**
* Sorts this list according to the order specified by the [compare] function.
*
* The [compare] function must act as a [Comparator].
*
* List<String> numbers = ['two', 'three', 'four'];
* // Sort from shortest to longest.
* numbers.sort((a, b) => a.length.compareTo(b.length));
* print(numbers); // [two, four, three]
*
* The default List implementations use [Comparable.compare] if
* [compare] is omitted.
*
* List<int> nums = [13, 2, -11];
* nums.sort();
* print(nums); // [-11, 2, 13]
*
* A [Comparator] may compare objects as equal (return zero), even if they
* are distinct objects.
* The sort function is not guaranteed to be stable, so distinct objects
* that compare as equal may occur in any order in the result:
*
* List<String> numbers = ['one', 'two', 'three', 'four'];
* numbers.sort((a, b) => a.length.compareTo(b.length));
* print(numbers); // [one, two, four, three] OR [two, one, four, three]
*/
fruits.sort((a, b) => a.compareTo(b));
assert(fruits[0] == 'apples');
六渣刷、Set
Dart 中的 Set
是一個(gè)無(wú)序集合鹦肿,里面不能保護(hù)重復(fù)的數(shù)據(jù)。 由于是無(wú)序的辅柴,所以無(wú)法通過(guò)索引來(lái)從 set 中獲取數(shù)據(jù):
var ingredients = new Set();
ingredients.addAll(['gold', 'titanium', 'xenon']);
assert(ingredients.length == 3);
// Adding a duplicate item has no effect.
ingredients.add('gold');
assert(ingredients.length == 3);
// Remove an item from a set.
ingredients.remove('gold');
assert(ingredients.length == 2);
- 使用
contains()
和containsAll()
來(lái)判斷 set 中是否包含 一個(gè)或者多個(gè)對(duì)象:
var ingredients = new Set();
ingredients.addAll(['gold', 'titanium', 'xenon']);
// Check whether an item is in the set.
assert(ingredients.contains('titanium'));
// Check whether all the items are in the set.
assert(ingredients.containsAll(['titanium', 'xenon']));
- 交集是兩個(gè) set 中都有的數(shù)據(jù)的子集:
var ingredients = new Set();
ingredients.addAll(['gold', 'titanium', 'xenon']);
// Create the intersection of two sets.
var nobleGases = new Set.from(['xenon', 'argon']);
// 拿到交集的值(Set類型)
var intersection = ingredients.intersection(nobleGases);
assert(intersection.length == 1);
assert(intersection.contains('xenon'));
七箩溃、Map
通常來(lái)說(shuō),Map 是一個(gè)鍵值對(duì)相關(guān)的對(duì)象碌嘀。 鍵和值可以是任何類型的對(duì)象涣旨。
Map中的鍵是唯一的,相同Key的值會(huì)覆蓋之前的數(shù)據(jù)股冗。
值可以為空字符串或者
null
所查找的鍵不存在霹陡,則返回
null
。使用
.length
來(lái)獲取Map
中鍵值對(duì)的數(shù)目止状。可使用
const
可以創(chuàng)建一個(gè)編譯時(shí)常量的Map
烹棉。
// 聲明并賦值
var gifts = {
// Keys Values
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
var nobleGases = {
// Keys Values
2: 'helium',
10: 'neon',
18: 'argon',
};
// 先聲明,后賦值
Map map1 = new Map();
map1['first'] = 'value1';
map1['second'] = 'value2';
map1['third'] = 'value3';
var map2 = new Map();
map2[2] = 'helium';
map2[10] = 'neon';
map2[18] = 'argon';
// 指定鍵值對(duì)的參數(shù)類型
var aMap = new Map<int, String>();
// Map的賦值怯疤,中括號(hào)中是Key浆洗,這里可不是數(shù)組
aMap[1] = '小米';
/*
Map中的鍵是唯一的,相同Key的值會(huì)覆蓋之前的數(shù)據(jù)
*/
aMap[1] = 'alibaba';
// map里面的value可以相同
aMap[2] = 'alibaba';
// map里面value可以為空字符串
aMap[3] = '';
// map里面的value可以為null
aMap[4] = null;
print(aMap);
// 檢索Map是否含有某Key
assert(aMap.containsKey(1));
/*
獲取鍵值對(duì)個(gè)數(shù),判斷Map是否為空時(shí)最好不要用lenth屬性集峦,
用isEmpty或者isNotEmpty伏社,可以提高性能
*/
print(aMap.length);
// 判斷List是否為空
bool isEmpty = aMap.isEmpty;
bool isNotEmpty = aMap.isNotEmpty;
//刪除某個(gè)鍵值對(duì)
aMap.remove(1);
print(aMap);
// 可使用const 可以創(chuàng)建一個(gè)編譯時(shí)常量的 Map。
final constantMap = const {
2: 'helium',
10: 'neon',
18: 'argon',
};
八少梁、Runes
在 Dart 中洛口,runes 代表字符串的 UTF-32 code points。
Unicode 為每一個(gè)字符凯沪、標(biāo)點(diǎn)符號(hào)第焰、表情符號(hào)等都定義了 一個(gè)唯一的數(shù)值。 由于 Dart 字符串是 UTF-16 code units 字符序列妨马, 所以在字符串中表達(dá) 32-bit Unicode 值就需要 新的語(yǔ)法了挺举。
通常使用 \uXXXX
的方式來(lái)表示 Unicode code point杀赢, 這里的 XXXX 是4個(gè) 16 進(jìn)制的數(shù)。 例如湘纵,心形符號(hào) (?) 是 \u2665
脂崔。 對(duì)于非 4 個(gè)數(shù)值的情況裳瘪, 把編碼值放到大括號(hào)中即可趋翻。 例如,笑臉 emoji (??) 是 \u{1f600}
师崎。
String 類 有一些屬性可以提取 rune
信息铺敌。 codeUnitAt
和 codeUnit
屬性返回 16-bit code units汇歹。 使用 runes
屬性來(lái)獲取字符串的runes
信息。
var clapping = '\u{1f44f}';
print(clapping); // ??
print(clapping.codeUnits); // [55357, 56399]
print(clapping.runes.toList()); // [128079]
Runes input = new Runes(
'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(new String.fromCharCodes(input)); // ? ?? ?? ?? ?? ??
九偿凭、Symbol
Symbol
字面量定義是編譯時(shí)常量产弹,一個(gè) Symbol object 代表 Dart 程序中聲明的操作符或者標(biāo)識(shí)符。 你也許從來(lái)不會(huì)用到 Symbol弯囊,但是該功能對(duì)于通過(guò)名字來(lái)引用標(biāo)識(shí)符的情況 是非常有價(jià)值的痰哨,特別是混淆后的代碼, 標(biāo)識(shí)符的名字被混淆了匾嘱,但是 Symbol 的名字不會(huì)改變斤斧。關(guān)于 symbols 的詳情,請(qǐng)參考 dart:mirrors - reflection奄毡。
使用 Symbol 字面量來(lái)獲取標(biāo)識(shí)符的 symbol 對(duì)象折欠,也就是在標(biāo)識(shí)符 前面添加一個(gè) #
符號(hào):
#radix
#bar