變數
變數的宣告
- var
- dynamic
- Object
-
宣告一個未初始化的變數,變數的型別可以更改
//變數 /// 三斜槓文件註釋 /// 返回型別 void 可以省略,省略後的返回值為 null void main(){ ///----------------------- 變數的宣告----------------- ///宣告一個未初始化的變數,變數的型別可改變 var data; data = "HelloWorld"; dynamic data1; data1 = "HelloWorld1"; data1 = 123; Object data2; data2 = 'HelloWorld2'; data2 = 123; print([data,data1,data2]); } /// 列印效果 lib/1-variables.dart:1: Warning: Interpreting this as package URI, 'package:flutter_test3/1-variables.dart'. [HelloWorld, 123, 123] 複製程式碼
-
宣告一個初始化的變數,變數型別不能再更改
var variablel = 'HelloWorld'; //變數是一個引用,名字為 variablel 的變數引用了一個內容為‘HelloWorld’的 String 物件。 // variablel = 123; //變數初始化後,variablel 變數的型別被推斷為String型別,其型別不能再改變 複製程式碼
-
dynamic 和 Object 宣告的變數初始化後,變數的型別仍可改變
dynamic variable2 = "HelloWorld"; variable2 = 123; // variable2.test();//呼叫不存在的test()方法,編譯通過,執行報異常。編譯階段不檢查型別 Object variable3 = 'HelloWorld'; variable3 = 123; // variable3.test();//呼叫不存在的test()方法,編譯不通過。編譯階段檢查型別 複製程式碼
-
使用確定型別顯示宣告變數,變數的型別不能再改變
String name3 = "HelloWorld"; // name3 =123; //變數的型別不能更改 複製程式碼
變數宣告總結
-
var: 如果沒有初始值,可以變成任何型別
-
dynamic:動態任意型別,編譯階段不檢查型別
-
Object 動態任意型別,編譯階段檢查型別
區別:
- 唯一區別 var 如果有初始值,型別被是鎖定
預設值
-
沒有初始化的變數預設值都是null
一切皆物件,物件的預設值是null
bool isEmpty; print((isEmpty == null)); 複製程式碼
final 和 const
-
被 final 或者 const 修飾的變數,變數型別可以省略
final FVariablel = "HelloWorld"; // final String FVariablel = "HelloWorld"; const cVariablel = "HelloWorld"; // const String cVariablel = "HelloWorld"; 複製程式碼
-
被 final 或 const 修飾的變數無法再去修改其值。
// fVariable1 = '123'; // cVariable1 = '123456'; 複製程式碼
-
如果是類級別常量,使用 static, const 。
DateTime; //可參照DateTime static const int monday = 1; 複製程式碼
-
const 可以使用其他 const 常量的值來初始化其值.
const width = 100; const height = 100; const square = width * height; 複製程式碼
-
const 賦值申明可省略
const List clist = [1, 2, 3]; // const List clist = const [1, 2, 3];//dart 2之前,const賦值必須用const宣告 print("\n\n\n"); print(clist); 複製程式碼
-
可以更改非 final,非 const 變數的值,即使它曾經具有 const 值
var varList = const [1, 2, 3]; final finalList = const [1, 2, 3]; const constList = [1, 2, 3]; print([varList, finalList, constList]); varList = [1]; // constList[1]; // finalList[1]; print("\n\n"); print([varList, finalList, constList]); 列印效果-- /*** * [[1, 2, 3], [1, 2, 3], [1, 2, 3]] * [[1], [1, 2, 3], [1, 2, 3]] */ 複製程式碼
-
const 導致的不可變性是可傳遞的
final List ls = [1, 2, 3]; ls[2] = 444; print(ls); const List cLs = [4, 5, 6]; // cLs[1] = 4; print("\n"); print(ls); 報錯: /*** * Unhandled exception: Unsupported operation: Cannot modify an unmodifiable list #0 UnmodifiableListBase.[]= (dart:_internal/list.dart:90:5) #1 main (package:flutter_test3/1-variables.dart:103:6) */ 複製程式碼
-
相同的 const 常量不會在記憶體中重複建立
final finalList1 = [1, 2, 3]; final finalList2 = [4, 5, 6]; print("\n"); print(identical(finalList1, finalList2)); //identical用於檢查兩個引用是否指向同一個物件 const constList1 = [1, 2]; const constList2 = [1, 2]; print("\n"); print(identical(constList1, constList2)); //identical用於檢查兩個引用是否指向同一個物件 複製程式碼
-
const 需要是編譯時常量
final DateTime finalDateTime = DateTime.now(); // const DateTime constDateTime = DateTime.now();//DateTime.now() 是執行期計算出來的值 const sum = 1 + 2; //使用內建資料型別的字面量通過基本運算得到的值 const aConstNum = 0; const aConstBool = true; const aConstString = 'a constant string'; const aConstNull = null; const validConstString = '$aConstNum, $aConstBool, $aConstString, $aConstNull'; print(validConstString); //使用計算結果為null或數字,字串或布林值的編譯時常量的插值表示式 複製程式碼
final 和 const 總結
共同點
- 宣告的型別可省略
- 初始化後不能再賦值
- 不能和 var 同時使用
區別(需要注意的地方)
- 類級別常量,使用 static ,const 。
- const 可使用其他 const 常量的值來初始化其值
- const 可使用其他 const 常量的值來初始化其值
- 可以更改非 final、非 const 變數的值,即使曾經具有 const 值
- const 導致的不可變性是可傳遞的
- 相同的 const 常量不會在記憶體中重複建立
- const 需要是編譯時常量
內建型別
Number 數值(num,int,double)
int i = 1; //整數型
double d = 1.0 ;//double b4-bit(雙精度)浮點數
int bitLength = i.bitLength;
print('bitLength:${bitLength}'); //bitLength 判斷 int 值需要多少位 bit 位。
double maxFinite = double.maxFinite;
print('maxFinite: ${maxFinite}'); //maxFinitedouble的最大值
//int和double都是num的子類
num n1 = 1;
num n2 = 1.0;
//支援 十進位制、十六進位制
int il = oxfff;
//科學計數法
double dl = 1.2e2; //120.0
//轉換
//String > int
int i2 = int.pasrse('1');
double d2 = 1;//當 double 的值為 int 值時,int 自動轉為 double
print('d2:${d2}');
int i2 = int.try.parse('1.0');//返回 null
//int > String
int is = 123;
String s = 123.toString;
複製程式碼
String 字串
//Dart 字串是 UTF-16 編碼的字元序列,可以使用單引號或者雙引號來建立字串
var name = 'HelloWorld';
//可以在字串中使用表示式: ${expression},如果表示式是一個識別符號,可以省略 {}。 如果表示式的結果為一個物件,則 Dart 會呼叫物件的 toString() 函式來獲取一個字串
var names = 'HelloWorld ${name}';
//r 字首可以建立一個 “原始 raw” 字串
var rawNames = r"HelloWorld ${name}";
print('name:${names}');
print('rawNames :${rawNames}');
//如果表示式的結果為一個物件,則 Dart 會呼叫物件的 toString() 函式來獲取一個字串。
pint(Map);
//可以使用三個單引號或者雙引號也可以 建立多行字串物件
var multiLinesString = '''
Java Android
Flutter''';
pint('mutiLinesString:${mutiLinesString}');
/// StringBuffer
var sb = StringBuffer(); //dart 2 可以省略 new
sb..write('aaa')..write('bbb')..write('ccc');//..級聯符實現鏈式呼叫
sb.writeAll([aaa,bbb,ccc],',');//第二個參數列示分隔符,將第一個引數列表裡的資料用這個分隔符拼接起來
pint('sb:${sb}');
複製程式碼
Booleans 布林值 (bool)
//bool :true 和 false
bool isNull;
print('isNull: ${isNull}');
複製程式碼
List 列表(陣列 List)
//宣告一個自動長度的陣列
List growableList = new List();
//List growbleList = new List()..length = 3;
growbleList..add(1)..add(2)..add('HelloWorld');
pint('growbleList: ${growbleList}');
//宣告一個固定長度的陣列
var list = List(6);// 這裡可以用 var 宣告,也可以用 List
list[0] = "Java";
list[1] = "Android";
list[2] = "Dart";
list[3] = "Flutter";
list[4] = "C++";
list[5] = "C"
pint('list:${list}');
//元素固定型別
var typeList = List<String>;
typeList..add("1")..add("2")..add("3");
pint('typeList:${typeList}');
//常用屬性-獲取第一個元素
String first = typeList.fisrt;
pint('typeList.fisrt:$typeFirst');
//最後一個元素
String last = typeList.last;
pint('typeList.last:${last}');
//元素個數
int typeListLength = typeList.length;
pint('typeListLength:${typeListLength}');
//元素是否為空
bool isEmpty = typeList.isEmpty;
pint('typeList.isEmpty:${isEmpty}');
//元素是否不為空
bool isNotEmpty = typeList.isNotEmpty;
pint('typeList.isNotEmpty:${isNotEmpty}');
//陣列倒序
Iterable reversed = typeList.reversed;
print('typeList.reversed:${reversed}');
// 常用方法 增刪改查,排序,洗牌,複製子列表
var list4 = [];
//增
list4.add(1);
pint('add 1:${list4}');
list4.addAll([2,3,4]);
print('addAll[2,3,4]:${list4}');
list4.insert(0,0);
print('insert(0,0) : ${list4}');
list4.insertAll(1,[5,6,7,8]);
print('insertAll(1,[5,6,7,8]) :${list4}');
//刪除
list4.remove(5);
print('remove 5 :${list4}');
list4.removeAt(2);
print('remove at 0:${list4}');
//改
list4[4] = 5;
print('updata list4[4] to 5 :${list4}');
//range
list4.fillRange(0,3,9);
print('fillRange updata list4[0] - list[2] to 9 :$list4');
Iterable getRange = list4.getRange(0,3);
print('getRange list4[0]-list[2]:${getRange}');
//查
var contains = list.contains(5);
print('contains 5 :${contains}');
var indexOf = list4.indexOf(1);
print('list4 indexOf 1 :${indexOf}');
int indexWhere = list4.indexWhere((test) => test == 5);
print('list4 indexWhere 5 :${indexWhere}');
// 排序
list4.sort();
print('list4 sort:${list4}');
//洗牌
list4.shuffle();
print('list4 shuffle:${list4}');
//複製子列表
var list5 = list4.shulist(1);
print('sublist(1) list5: ${list5}');
//操作符
var list6 =[8,9];
print('list6:${list6}');
var list7 = list5 + list7;
print('list5 + list6:${list7}');
複製程式碼
Maps 鍵值對集合 (Map)
//宣告一個動態型別的 Map
var dynamicMap = Map();
dynamicMap['name'] = 'HelloWorld';
dynamicMap[1] = 'android';
print('dynamicMap :${dymaicMap}');
//強型別
var map = Map<int,String>();
map[1] = 'java';
map[2] = 'Android';
print('map :${map}');
//也可以這樣宣告
var map1 = {'name':'Java',1:'android'};
map1.addAll({'name','Flutter'});
print('map1:${map1}');
//常用屬性
// print(map.isEmpty); //是否為空
// print(map.isNotEmpty); //是否不為空
// print(map.length); //鍵值對個數
// print(map.keys); //key 集合
// print(map.values); //value集合
複製程式碼
Set 集合 (Set)
// Set 無重複列表
var dynamicSet = Set();
dynamicSet.add('java');
dynamicSet.add('Android');
dynamicSet.add('Flutter');
dynamicSet.add('C/C++');
dynamicSet.add('1');
dynamicSet.add('1');
print('dynamicSet :${dynamicSet}');
//常用屬性與 List 類似
//常用方法 增刪改查與 List 類似
var set1 = {'java','Android'};
print('set1: ${set1}');
var differencel2 = set1.difference(set2);
var difference21 = set1.difference(set1);
print('set1 difference set2 :${differencel2}');//返回 set1 集合裡有但 set2 裡沒有的元素集合
print('set2 difference set1 :${difference2l}');//返回 set2 集合裡面有但 set1 裡沒有的元素集合
var intersection = set1.intersection(set2);
print('set1 set2 交集 :${intersection}');//返回 set1 和 set2 的交集
var union = set1.union(set2);
print('set2 set1並集:${union}');
set2.retainAll(['java','Android']);//只保留(要保留的元素要在原 set 中存在)
print('set2 只保留 java Android :${set2}');
複製程式碼
Runes 符號字元
//Runes用於在字串中表示Unicode字元 //https://copychar.cc/emoji/
String runesStr = '?';
print(runesStr);
print(runesStr.length); //表示佔 2 個 16 位字元
print(runesStr.runes.length); //表示佔 1 個 32 位字元
Runes runes = new Runes('\u{1f605} \u6211');
var str1 = String.fromCharCodes(runes); //使用String.fromCharCodes顯示字元圖形
print(str1);
String str2 = '\u{1f605} \u6211'; //如果非4個數值,需要把編碼值放到大括號中
print(str2)
複製程式碼
Symbols 識別符號
//Symbol識別符號 主要是反射用,現在mirrors已經被移除了
複製程式碼
函式
定義
-
可在函式內定義
void main(){ int add(int x,int y){ return x + y; } print(add(1,2)); } 複製程式碼
-
定義函式時可省略型別
void main(){ add( x, y){ //不建議省略 return x + y; } print(add(3,4)); } 複製程式碼
-
支援縮寫語法 =>
void main(){ int add2(int x,int y) => x + y; /// 等同於 int add3(int x,int y){ return x + y; } print(add2(3,4)); print(add3(3,4)); } 複製程式碼
可選引數
-
可選命名引數,使用 {param1,param2,...} 的形式來指定命名引數
void main(){ int add3({int x,int y,int z}){ x ?? = 1; x ?? = 2; x ?? = 3; return x + y + z; } print(add3()); } 複製程式碼
-
可選位置引數,把可選引數放在 [ ] 中,必填引數要放在可循引數前面
void main(){ int add(int x,[int y ,int z]){ y ?? = 2; z ?? = 3; return x + y + z; } print(add(1)); } 複製程式碼
-
可選命名引數預設值(預設值必須是編譯時常量),目前可使用等號 ‘=’ 或 ‘:’,Dart SDK 1.21 之前只能用冒號,冒號的支援以後會移除,所以建議使用等號
void main(){ int add5(int x,[int y =2,int z = 3]){ return x + y +z; } //前面的必填引數沒有名字 print(add(5,y:10,z:20)); } //可選位置引數預設值(預設值必須是編譯時常量),只能使用等號 “=” void mian (){ int add6(int x,[int y = 2,int z = 3]){ return x + y + z; } print(add6(1)); } //使用 list 或者 map 作為預設值,但必須是 const void func({List list = const [1,2,3],Map map = const {1:1,'fun' :'全棧'}}){ //TODO ---- } 複製程式碼
匿名函式
-
可賦值給變數,通過變數呼叫
//無參匿名函式 var anonFunc1 = () => print('無參匿名函式'); anonFunction(); //有參匿名函式 var anonFunc = (name) => 'I am ${name}'; print(anonFunc('DevYK')); //通過()呼叫,不推薦 (() => print('不推薦'))(); 複製程式碼
-
可在其他函式中直接呼叫或傳遞給其他函式
void main(){ List test(List list,String func(str)){ for(var i =0;i < list.length;i++){ list[i] = func(list[i]); } return list; } var list = ['a','b','c','d','e']; print(test(list,(str) => str * 2)); // String * int ,Dart 和 Py 可以這樣用。 //List.forEach()就用的匿名函式 List list1 = [11, 12, 13]; list1.forEach((item) => print('$item')); } 複製程式碼
閉包
-
返回 Function 物件(閉包)
void main(){ Function makeAddFunc(int x){ x++; return (int y) => x + y; } var addFunc = makeAddFunc(2); print(addFunc(3)); } 複製程式碼
函式別名
-
可以指向任何同簽名的函式
void main(){ MyFunc myFunc; myFunc = subtsract; myFunc(4,2); myFunc = divide; myFunc(4,2); //typeDef 作為引數傳遞給引數 calculator(4,2,subtsract); } //函式別名 typedef MyFunc(int a,int b); //根據 MyFunc 相同的函式簽名定義兩個函式 subtsract(int a,int b){ print('subtsract: ${a-b}'); } divide(int a,int b){ print('divide: ${a / b}'); } //typedef 也可以作為引數傳遞給函式 calculator(int a,int b,MyFunc func){ func(a,b); } 複製程式碼
操作符
字尾操作
-
條件成員訪問 和 . 類似,但是左邊的操作物件不能為 null,例如 foo?.bar 如果 foo 為 null 則返回 null,否則返回 bar 成員。
String a; print(a?.length); 複製程式碼
取商操作符
-
被除數 ÷ 除數 = 商 ... 餘數,A ~/ B = C,這個C就是商。相當於Java裡的 /
print(2 / 3); print(2 ~/ 3); 複製程式碼
型別判定操作符
-
as、is、is! 在執行時判定物件型別
void main(){ //as 型別轉換 num iNum = 1; num dNum = 1.0; int i = iNum as int; double d = dNum as double; print([i,d]); // is 如果物件是指定的型別返回 true print(iNum is int); Child child; Child childl = new Child(); print(child is Parent);//child is Null print(childl is Parent); // is! 如果物件是制定的型別返回 False print(iNum is! int); } class Parent {} class Child extends Parent {} 複製程式碼
條件表示式
-
三目運算子 condition ? expr1 : expr2
bool isFinish = true; String textVal = isFinish ?'yes':'no'; // expr1 ?? expr2,如果 expr1 是 non-null,返回其值; 否則執行 expr2 並返回其結果。 bool isPaused; isPaused = isPaused ?? false; //或者 isPaused ??= false; 複製程式碼
級聯操作符
-
.. 可以在同一個物件上 連續呼叫多個函式以及訪問成員變數。 嚴格來說, 兩個點的級聯語法不是一個操作符。 只是一個 Dart 特殊語法。
StringBuffer sb = new StringBuffer(); sb ..write('Java') ..write('Android') ..write('\n') ..writeln('DevYK'); 複製程式碼
流程控制語句
if else
for , forEach , for-in
-
forEach
collection.forEach(item) => print('forEach: ${item}'); 複製程式碼
-
for-in
for (var item in collection) { print('for-in: $item'); } 複製程式碼