Dart基础系列:
说明:
Dart系列的开篇(Dart简介)总结了Dart语言的相关知识,涉及到一些基础的概念,并介绍了如何搭建其开发环境。从这一篇开始,我将对Dart的语法进行总结,分为上下两篇,其中本篇的内容如下:
内容:
- 关键字
- 数据类型
变量与常量
数据类型(内置类型) - 操作符
算数运算符;关系运算符;逻辑运算符;赋值运算符;
位和移位操作符;条件表达式;类型判定操作符;其他操作符
级联操作符 - 控制语句
- 注释
一、关键字
| 关键字 | |||
|---|---|---|---|
| abstract [1] | do | import [1] | super |
| as [1] | var | continue | dynamic [1] |
| assert [2] | else | interface | sync *[2] |
| enum | is | implements [1] | export [1] |
| async *[2] | this | library [1] | throw |
| await | new | covariant | true |
| break | null | external [1] | factory [1] |
| case | try | extends | typedef [1] |
| catch | false | operator [1] | switch |
| class | final | finally | void |
| const | part [1] | rethrow | while |
| in | for | return | with |
| mixin | get [1] | set [1] | yield *[2] |
| default | if | static [1] | deferred [1] |
带有**[1]** 的关键字是 内置关键字。避免把内置关键字当做标识符使用。 也不要把内置关键字 用作类名字和类型名字。 有些内置关键字是为了方便把 JavaScript 代码移植到 Dart 而存在的。 例如,如果 JavaScript 代码中有个变量的名字为 factory, 在移植到 Dart 中的时候,你不必重新命名这个变量。
带有**[2]** 的关键字,是在 Dart 1.0 发布以后又新加的,用于 支持异步相关的特性。 你不能在标记为 async*、或者 sync* 的方法体内 使用 async、 await、或者 yield 作为标识符。 详情请参考:异步支持。
所以其他单词都是 保留词。 你不能用保留词作为关键字。
二、数据类型
1、变量与常量
-
变量声明与初始化:
1.使用var声明变量,此时没有明确类型,编译的时候根据值明确类型
2.明确变量类型,来帮助 Dart 去捕获异常以及 让代码运行的更高效
3.未初始化时,变量默认值为null
4.如果对象不限于单一类型(没有明确的类型),请使用Object或dynamic关键字``` var name = ‘Bob’; Object name1 = '张三'; //动态类型 dynamic name2 = '李四'; // 显示声明将被推断类型, 可以使用String显示声明字符串类型 String name3 = 'Bob' ; -
final and const
1.被final和const修饰的变量只能赋值一次,不可更改变量值
2.一个 final 变量只能被初始化一次; const变量是一个编译时常量,(Const变量是隐式的final),如果 const 变量在类中,请定义为 static const。
3.被final或者const修饰的变量,变量类型可以省略,建议指定数据类型。
4.被final修饰的顶级变量或类变量在第一次声明的时候就需要初始化,否则会提示错误:// The final variable 'outSideFinalName' must be initialized. final String outSideFinalName5.const关键字不只是声明常数变量,您也可以使用它来创建常量值,以及声明创建常量值的构造函数,任何变量都可以有一个常量值。``` // 注意: [] 创建的是一个空的list集合 // const []创建一个空的、不可变的列表(EIL)。 var varList = const []; // varList 当前是一个EIL final finalList = const []; // finalList一直是EIL const constList = const []; // constList 是一个编译时常量的EIL// 可以更改非final,非const变量的值 // 即使它曾经具有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"];
2、数据类型(内置类型)
2.1、num(数值)
1、int:其取值通常位于 -253 和 253 之间
2、double:64-bit (双精度) 浮点数,符合 IEEE 754 标准。
3、数值型操作:
-
运算符:
+、-、*、/、~/、%
其中~/为整除 -
常用属性:
isNaN(是否非数字),isEven(是否为偶数),isOdd(是否为奇数) -
常用方法:
abs(),round(),floor(),ceil(),toInt(),`toDouble()```` int a = 1; print(a);double b = 1.12; print(b);
// String -> int int one = int.parse('1'); // 输出3 print(one + 2);
// String -> double var onePointOne = double.parse('1.1'); // 输出3.1 print(onePointOne + 2);
// int -> String String oneAsString = 1.toString(); // The argument type 'int' can't be assigned to the parameter type 'String' //print(oneAsString + 2); // 输出 1 + 2 print('$oneAsString + 2'); // 输出 1 2 print('$oneAsString 2');
// double -> String 注意括号中要有小数点位数,否则报错 String piAsString = 3.14159.toStringAsFixed(2); // 截取两位小数, 输出3.14 print(piAsString);
String aString = 1.12618.toStringAsFixed(2); // 检查是否四舍五入,输出1.13,发现会做四舍五入 print(aString);
2.2、String(字符串)
1、String的创建:
- 使用单引号'',双引号""
- 使用三个 引号'''或双引号""" 创建多行字符串
- 使用r 创建原始 raw 字符串
var s1 = '单引号字符串'; var s2 = "双引号字符串"; var s3 = ''' 单引号多创建的多行的字符串, 第二行 '''; var s4 = """ 双引号多创建的多行的字符串, 第二行 """; //使用r创建原始’raw‘字符串,\n不换行 var s5 = r"使用r创建原始’raw‘字符串,\n不换行";
2、字符串操作:
-
运算符:
+,*,==,[],1 String a = "hello"; 2 String b = a + " Dart!"; 3 //hello Dart! 4 print(b); 5 6 String c = b*2; 7 //hello Dart!hello Dart! 8 print(c); 9 10 String d = "hello Dart!"; 11 //true 12 print(d==b); 13 14 String e = d[0]; 15 //h 16 print(e); -
插值表达式:
${expression}1int e1 = 1; 2int e2 = 2; 3//a = 1 4print("a = $a"); 5//e1 + e2 = 3 6print("e1 + e2 = ${e1 + e2}"); -
常用属性:
length(长度),isEmpty(是否为空),isNotEmpty(是否非空) -
常用方法:
contains(),subString(),startsWith(),endsWith(),indexOf(),lastIndexOf(),toLowerCase(),toUpperCase(),trim(),trimLeft(),trimRight(),split(),replaceXxx() -
更多API详见官网:String class
3、StringBuffer:
-
使用
StringBuffer创建字符串,当调用其toString()函数时,才会创建一个 新的String对象。 -
write():将参数字符串加入StringBuffer对象中 -
writeAll():此函数有一个可选的参数来指定每个字符串的分割符``` var sb = new StringBuffer(); //这里用到了级联操作符 sb..write('Use a StringBuffer for ') ..writeAll(['efficient', 'string', 'creation'], ' ') ..write('.');var fullString = sb.toString(); //Use a StringBuffer for efficient string creation. printI(fullString);
2.3、bool(布尔型)
1、使用bool表示布尔型
2、布尔值只有个true,false,它们都是编译时常量。
3、Dart的类型安全意味着您不能使用 if(nonbooleanValue) 或 assert(nonbooleanValue) 等代码, 相反Dart使用的是显式的检查值。
2.4、List(数组、列表)
1、List的创建:
- 创建List:```
var lvs = [1, 2, 3];
- 创建不可变的List:```
//其中的值不能修改
var lcs = const [1, 2, 3];
//报错:unsupported operation: Cannot modify for an unmodifiable list
lcs[0] = 5;
- 构造创建:```
var lns = new List();
2、常用操作:
-
[]取值,length数组长度 -
方法:
add()添加元素,insert()在指定位置插入,
remove()移除元素,clear()清空数组,
indexOf()获取指定元素位置,lastIndexOf()倒序获取指定元素位置,
sort()排序,sublist()截取数组,shuffle(),
asMap()转换为Map,forEach()循环遍历,
更多API详见官网:List<E> class1 //创建一个int类型的list 2 List list = [10, 7, 23]; 3 // 输出[10, 7, 23] 4 print(list); 5 6 // 使用List的构造函数,也可以添加int参数,表示List固定长度,不能进行添加 删除操作 7 var fruits = new List(); 8 9 // 添加元素 10 fruits.add('apples'); 11 12 // 添加多个元素 13 fruits.addAll(['oranges', 'bananas']); 14 15 List subFruits = ['apples', 'oranges', 'banans']; 16 // 添加多个元素 17 fruits.addAll(subFruits); 18 19 // 输出: [apples, oranges, bananas, apples, oranges, banans] 20 print(fruits); 21 22 // 获取List的长度 23 print(fruits.length); 24 25 // 获取第一个元素 26 print(fruits.first); 27 28 // 获取元素最后一个元素 29 print(fruits.last); 30 31 // 利用索引获取元素 32 print(fruits[0]); 33 34 // 查找某个元素的索引号 35 print(fruits.indexOf('apples')); 36 37 // 删除指定位置的元素,返回删除的元素 38 print(fruits.removeAt(0)); 39 40 // 删除指定元素,成功返回true,失败返回false 41 // 如果集合里面有多个“apples”, 只会删除集合中第一个改元素 42 fruits.remove('apples'); 43 44 // 删除最后一个元素,返回删除的元素 45 fruits.removeLast(); 46 47 // 删除指定范围(索引)元素,含头不含尾 48 fruits.removeRange(start,end); 49 50 // 删除指定条件的元素(这里是元素长度大于6) 51 fruits.removeWhere((item) => item.length >6); 52 53 // 删除所有的元素 54 fruits.clear(); -
说明:List 是泛型类型,所以可以指定里面所保存的数据类型
1 // This list should contain only strings. 2 var fruits = new List<String>(); 3 4 fruits.add('apples'); 5 var fruit = fruits[0]; 6 assert(fruit is String); 7 8 // Generates static analysis warning, num is not a string. 9 fruits.add(5); // BAD: Throws exception in checked mode.
2.5、Set(无序集合)
1、Dart 中的 Set 是一个无序集合,里面不能保护重复的数据。 由于是无序的,所以无法通过索引来从 set 中获取数据。
2、相关方法:
add() 添加一个元素, addAll() 添加一个数组
contains() 是否包含一个元素,containsAll() 是否包含多个元素
intersection() 获取两个集合的交集
更多API详见官网:Set<E> class
1 void main() { 2 var sts = new Set(); 3 sts.add("1"); 4 sts.addAll(['gold', 'titanium', 'xenon']); 5 sts.add("1"); //重复添加相同元素被覆盖 6 7 //{1, gold, titanium, xenon} 8 print(sts); 9 10 //titanium 11 print("" + sts.elementAt(2)); 12 13 //sts==>{1, gold, titanium, xenon} 14 print("sts==>$sts"); 15 16 var sts2 = new Set.from(['xenon', 'argon']); 17 //sts2==>{xenon, argon} 18 print("sts2==>$sts2"); 19 20 var sts3 = sts.intersection(sts2); 21 //sts3==>{xenon} 22 print("sts3==>$sts3"); 23 }
注: List<E>和Set<E>都继承自EfficientLengthIterable<T> ,并最终继承Iterable<E>类。
2.6、Map(集合)
1、说明:
· map 通常也被称之为 字典或者 hash ,也是一个无序的集合,里面 包含一个 key-value 对。map 把 key 和 value 关联起来可以 方便获取数据。和 JavaScript 不同的是, Dart objects 不是 maps。
· 键和值都可以是任何类型的对象。
· 每个 键 只出现一次, 而一个值则可以出现多次。
2、创建:
1 //方式一: 2 var map1 = { 3 "one" : [1, "strValue", true], 4 "two" : "twoValue", 5 }; 6 //创建不可变Map 7 var mapConst = const { 8 "one" : [1, "strValue", true], 9 "two" : "twoValue", 10 }; 11 12 //方式二:未指定泛型类型 13 var map2 = new Map(); 14 15 //方式二:指定泛型类型 16 var map3 = new Map<int, String>();
3、常用属性/方法:
length Map长度, keys 返回所有key值,values 返回所有的value值
isEmpty() 是否为空Map, isNotEmpty() 是否为非空Map
[] 新增一个元素,remove() 移除一个元素,并将元素返回
containsKey() 是否包含一个key
putIfAbsent(key, function) 设置 key 的值,但是只有该 key 在 map 中不存在的时候才设置这个值,否则 key 的值保持不变。该函数需要 一个方法返回 value。
forEach() 遍历Map
1 var map1 = { 2 "one" : [1, "strValue", true], 3 "two" : "twoValue", 4 }; 5 6 //null 7 print(map1["x"]); 8 //[1, strValue, true] 9 print(map1["one"]); 10 11 //true 12 print(map1.containsKey("one")); 13 14 var result = map1.remove("two"); 15 //result==>twoValue,,map1==>{one: [1, strValue, true]} 16 print("result==>$result,,map1==>$map1"); 17 18 //提示:the argument type 'int' can't be assigned to be parameter type 'String' 19 //map1[1] = 123; 20 21 var map11 = { 22 "one" : [1, "strValue", true], 23 "two" : "twoValue", 24 2 : new List() 25 }; 26 //不会提示错误 27 map11[1] = 123; 28 29 //新增一个元素 30 map1["three"] = "addValue"; 31 32 var keys = map1.keys; 33 //keys==>(one, three) 34 print("keys==>$keys"); 35 var values = map1.values; 36 //values==>([1, strValue, true], addValue) 37 print("values==>$values"); 38 39 map1.putIfAbsent("four", ()=> 1+2); 40 map1.putIfAbsent("four", ()=> "返回一个value"); 41 //map1==>{one: [1, strValue, true], three: addValue, four: 3} 42 print("map1==>$map1"); 43 print("=========================="); 44 45 /* 46 one==>[1, strValue, true] 47 three==>addValue 48 four==>3 49 */ 50 map1.forEach((key, value)=> { 51 print("$key==>$value") 52 }); 53 54 print("=========================="); 55 /* 56 one==[1, strValue, true] 57 three==addValue 58 four==3 59 */ 60 for(var me in map1.entries) { 61 print("${me.key}==${me.value}"); 62 }
说明:
1、从上面的代码可以看出,在map中,如果初始的key值都是同一类型,则在通过[] 方式添加的时候,只能添加相同类型的值作为key。
2、虽然 Map 没有实现 Iterable,但是 Map 的 keys 和 values 属性实现了 Iterable。
1 Iterable<K> get keys; 2 Iterable<V> get values;
3、和Java一样,在Map中也有一个内部类MapEntry<K, V>,可以通过其属性entries获取到MapEntry<K, V> 类型的迭代器Iterable,以此来进行遍历。
2.7、dynamic(动态类型)
1、注意:
dynamic并非Dart中的内置类型,
没有指定类型的变量的类型为 dynamic,
dynamic 一般在使用泛型时使用
2、示例:
1dynamic a = 10; 2//a==>10 3print("a==>$a"); 4a = "六六六"; 5//a==>六六六 6print("a==>$a"); 7 8var ls = new List<dynamic>(); //泛型,会在后面总结 9ls.add("哈哈"); 10ls.add(333); 11//ls==>[哈哈, 333] 12print("ls==>$ls");
2.8、runes(符号文字)[不常用]
-
简介:
在 Dart 中,runes 代表字符串的 UTF-32 code points。Unicode 为每一个字符、标点符号、表情符号等都定义了 一个唯一的数值。 由于 Dart 字符串是 UTF-16 code units 字符序列, 所以在字符串中表达 32-bit Unicode 值就需要 新的语法了。
可以实现一些表情的符号文字。
-
Unicode code point的表示方式:
\uXXXX这里的 XXXX 是4个 16 进制的数。
-
示例:
1main() { 2 var clapping = '\u{1f44f}'; 3 print(clapping); 4 print(clapping.codeUnits); 5 print(clapping.runes.toList()); 6 7 Runes input = new Runes( 8 '\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}'); 9 print(new String.fromCharCodes(input)); 10} 11 12//打印结果:=============================== 13👏 14[55357, 56399] 15[128079] 16♥ 😅 😎 👻 🖖 👍
2.9、Symbols(标志)[不常用]
-
简介:
一个 Symbol object 代表 Dart 程序中声明的操作符或者标识符。此标识符常用于对于通过名字来引用标识符的情况,特别是混淆后的代码, 标识符的名字被混淆了,但是 Symbol 的名字不会改变。
Symbol 字面量定义的是编译时常量。
-
使用:
使用 Symbol 字面量来获取标识符的 symbol 对象,也就是在标识符 前面添加一个 # 符号:1#radix 2#bar
关于 symbols 的详情,请参考 dart:mirrors - reflection。
三、操作符
1、算数运算符:
+加、-减、*乘、/除、~/取整、%取模(余)、-expr负数++expr先递增、expr++后递增、--expr先递减、expr--后递减
2、关系运算符:
==相等、!=不等、>=大于等于、>大于、<=小于等于、<小于
3、逻辑运算符:
!取反、&&并且、||或者
4、赋值运算符:
=等于、+=加等于、-=减等于、
*=乘等于、/=除等于、
%=取模(余)等于、~/=取整等于
<<=左移等于、>>=右移等于
^=非等于、&=且等于、|=或等于
??=判空等于:如果??=左边的变量为无值,则将右边的值赋值给变量,否则不赋值``` int a = 10; int b; a ??= 20; b ??=5; //a = 10 a有值10,所以不会赋值20 print("a = $a"); //b = 5 b无值,则将5赋值给b print("b = $b");
5、位和移位操作符
& 且、| 或、^ 非、<< 左移、>> 右移
5、条件表达式
condition ? expr1 : expr2 三目运算符
expr1 ?? expr2 返回其中不为空的表达式执行结果
1String a = "Hello"; 2String b = ""; 3String c = "Dart"; 4String d = a ?? b; 5String e = b ?? c; 6//d = Hello 7print("d = $d"); 8//e = Dart 9print("e = $e");
6、类型判定操作符
as、is、和 is! 操作符是在运行时判定对象
as:类型转换
is:如果对象是指定的类型返回 True
is!:如果对象是指定的类型返回 False
具体例子参考面向对象的总结
7、其他操作符
():使用方法。代表调用一个方法[]:访问 List。访问 list 中特定位置的元素
.:访问 Member(成员)。访问元素,例如 foo.bar 代表访问 foo 的 bar 成员
?.:条件成员访问。和.类似,但是左边的操作对象不能为 null,例如foo?.bar如果foo为null则返回null,否则返回bar成员
8、级联操作符
..:级联操作符 (..) 可以在同一个对象上 连续调用多个函数以及访问成员变量。使用级联操作符可以避免创建临时变量,并且写出来的代码看起来更加流畅。(具体详见面向对象中的例子)
1querySelector('#button') // Get an object. 2 ..text = 'Confirm' // Use its members. 3 ..classes.add('important') 4 ..onClick.listen((e) => window.alert('Confirmed!'));
说明:
第一个方法 querySelector() 返回了一个 selector 对象。后面的级联操作符都是调用这个对象的成员,并忽略每个操作所返回的值。
四、控制语句
-
if...else,if...else if,if...else if...else``` int score = 95; if (score > 90) { print("优秀"); } else if (score > 60) { print("及格"); } else { print("完蛋玩意儿"); } //优秀
-
for,for...in``` var list = [1, 2, 3, 4, 5]; for (var item in list) { print(item); }
-
while do-while``` int count = 5; while(count > 0) { print("index => $count"); count--; }
1int length = 5; 2do { 3 print("index ==> $length"); 4 length--; 5} while(length > 0); -
break continue``` List ls = [1, 2, 3, 4, 5, 6, 7, 8, 9]; for (var i = 1; i<=ls.length; i++) { if (i%4==0) { break; } if (i%3==0) { continue; } print("index ==> ${ls[i]}"); }
//index ==> 2 //index ==> 3
-
switch...case
其中可以使用跳转标签(自定义标签名称)Stirng lang = “Dart"; switch (lang) { D: case "Dart": print("This is Dart!"); break; case "Java": print("This is Java!"); break; case "Flutter": print("This is Flutter!"); continue D; //break; //不需要了 default: print("This is NONE!"); break; }打印结果为:``` This is Flutter! This is Dart! -
assert (断言)
1、如果条件表达式结果不满足需要,则可以使用 assert 语句俩打断代码的执行。
2、断言只在检查模式下运行有效,如果在生产模式 运行,则断言不会执行。
3、assert方法的参数可以为任何返回布尔值的表达式或者方法。
如果返回的值为 true, 断言执行通过,执行结束。 如果返回值为 false, 断言执行失败,会抛出一个异常 AssertionError``` // 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'));
四、注释
-
Dart 支持单行注释、多行注释和 文档注释。
-
单行注释:
单行注释以//开始。//后面的一行内容 为 Dart 代码注释。1 main() { 2 // TODO: refactor into an AbstractLlamaGreetingFactory? 3 print('Welcome to my Llama farm!'); 4 } -
多行注释:
多行注释以/*开始,*/结尾。 多行注释可以嵌套。1 main() { 2 /* 3 * This is a lot of work. Consider raising chickens. 4 5 Llama larry = new Llama(); 6 larry.feed(); 7 larry.exercise(); 8 larry.clean(); 9 */ 10 } -
文档注释:
文档注释可以使用///开始, 也可以使用/**开始 并以*/结束。在文档注释内, Dart 编译器忽略除了中括号以外的内容。 使用中括号可以引用
classes、methods、fields、top-level variables、functions、 和parameters。中括号里面的名字使用 当前注释出现地方的语法范围查找对应的成员。1 /// A domesticated South American camelid (Lama glama). 2 /// 3 /// Andean cultures have used llamas as meat and pack 4 /// animals since pre-Hispanic times. 5 class Llama { 6 String name; 7 8 /// Feeds your llama [Food]. 9 /// 10 /// The typical llama eats one bale of hay per week. 11 void feed(Food food) { 12 // ... 13 } 14 15 /// Exercises your llama with an [activity] for 16 /// [timeLimit] minutes. 17 void exercise(Activity activity, int timeLimit) { 18 // ... 19 } 20 }使用 SDK 中的 文档生成工具可以解析文档并生成 HTML 网页。 关于生成的文档示例,请参考 Dart API 文档。 关于如何 组织文档的建议,请参考 Dart 文档注释指南。
