作者:opLW
目的:在阅读Dart概览后进行的总结,主要记录Dart相比Java的新特性,包括许多亲自实验后的总结。如有错误还望指正😄
其他文章:
Dart – 较Java新特性(二)
Dart – 较Java新特性(三)
目录
1.变量
- 1.1 变量类型 Dart中没有基本数据类型的说法,任何变量都是类的实例并且这些类都继承自
Object
。 - 1.2 变量的默认值 Dart中所有变量默认值都为
null
,不像Java中基本类型有其对应的默认值。 - 1.3 变量的声明
- var Dart中除了可以像Java一样明确声明变量类型外,还引入
var
标识符来声明变量,被var
修饰的变量的类型由系统根据变量实际值进行推断。String name = 'Bob'; var name = 'Bob';
- dynamic
dynamic
标识符修饰变量时,相当于告诉编译器开发者自己能保证代码正确,不用编译器对这个变量的进行检查。如下代码在编译时不会出现警告,而运行时会抛出异常,因为A
类没有foo
这个方法。
使用void main() { dynamic a = A(); a.foo(); } class A {}
dynamic
标识符时,开发者需要自行保证正确。
注意 Dart中的集合类,如果不特别声明泛型的类型,那么默认使用dynamic
代替。
- var Dart中除了可以像Java一样明确声明变量类型外,还引入
- 1.4 变量的实例化
- new关键字 在实例化对象时,
new
关键字变为可选,即可以省略new
关键字
- new关键字 在实例化对象时,
2.常量
- 2.1 final 与Java一样,
final
修饰的变量代表其只能被设置一次。因为Dart中没有基本变量,所以可以认为被final
修饰的变量,其不能引用其他对象。- 由于Dart能进行类型推断,所以可以声明变量时可以省略类型。
final String nickname = 'Bobby'; final name = 'Bob'; // Without a type annotation name = 'Alice'; // Error: 一个 final 变量只能被设置一次。
- 由于Dart能进行类型推断,所以可以声明变量时可以省略类型。
- 2.2 编译期常量:const
const
相对于final
的要求更高,除了被修饰变量不能引用其他对象外,const
修饰的变量为编译期常量,即在编译器编译代码时就确定变量的值。- 如果
const
修饰的常量属于类级别的,那么应该用static const
修饰,类似于Java
用public static final
修饰的变量。void main() { print(A.str); const str1 = 'I am a Char too'; print(str1); } class A { static const str = 'I am a Char'; }
- 在字符串中含有算术表达式或变量时,只要变量是编译时常量, 那么算术表达式的结果也是编译时常量;
void main() { print(A.number2); } class A { static const c = 1; static const d = 2; static const number2 = 'I am ${c + d}'; }
const
除了用于声明编译期常量外,也可用于创建编译期常量,这需要该类拥有常量构造函数const a = [1,2,3]; // const用于声明变量 //a = [2,3,4]; 再次对a赋值。发生错误,因为a是一个const类型的变量 var b = const [3, 4, 5]; // 创建编译器常量 //b[0] = 10; 发生错误,因为此时的b指向一个常量,不能对其内容进行修改 b = [4, 5, 6]; // 正常,因为b是一个var类型变量 b[0] = 10; //正常,因为此时b已经指向另一个不为const的变量了 var a = const[1,2,3]; var b = const[1,2,3]; if (identical(a,b)) { print(true); } // 输出true,因为a和b都指向同一个编译期常量
3.内建类型 (Dart自带的类型)
- 3.1 数字类型 Dart中没有
float
类型,只有double
和int
。int
取值范围在Dart VM上为 -263 到263-1- 只要值中含有小数点那么就认为是
double
类型 - 从Dart 2.1开始,必要的时候
int
字面量会自动转换成double
类型。double z = 1; // 相当于 double z = 1.0.
- 3.2 字符串
- Dart中字符串可用单引号或者双引号进行声明。
String str = 'The code can\'t be set' String str = "The code can't be set"
- 如果在用单引号包括的字符串中使用单引号,则需要进行转义。
- 如果在用双引号包括的字符串中使用双引号,同样需要进行转义。
- 但双引号包括的字符串中使用单引号则不需要转义。
- 使用连续三个单引号或者三个双引号实现多行字符串对象的创建。
var s1 = ''' You can create multi-line strings like this one. '''; var s2 = """This is also a multi-line string.""";
- 字符串模板 字符串可以通过
${expression}
的方式内嵌表达式。 如果表达式是一个标识符,则 {} 可以省略。String str1 = "I am ${a + b}" String str2 = "I am $a"
- 原始字符串 通过在字符串前面添加“r”字符,让字符串保持原生输出,即字符串内容是什么就输出什么。
注意:当原生字符串中含有单引号时,需要使用双引号包裹。否则由于转义字符被忽略,将导致void main() { int a = 1; int b = 2; final str1 = r"I am ${a + b} can\'t be 3"; print(str1); // 输出:I am ${a + b} can\'t be 3 final str2 = r'I am ${a + b} can\'t be 3'; print(str2); // 错误,详细原因见下方 }
\'
中的单引号被误认为是字符串结束,引发错误。
- Dart中字符串可用单引号或者双引号进行声明。
- 布尔值 Dart中使用
bool
声明布尔值,有true
和false
两个值并且这两个值都为编译期常量。
4.集合
- 4.1 List
var list = [1, 2, 3]; // 通过方括号创建 var length = list.length; // 获取list对象的length属性 list[1] = 2; // 通过list[i]访问或设置元素
- 4.2 Map
// 通过键值对和中括号的形式创建Map var gifts = { // Key: Value 'first': 'partridge', 'second': 'turtledoves', 'fifth': 'golden rings' }; // 系统自动推断为Map<String,String>类型 var nobleGases = { 2: 'helium', 10: 'neon', 18: 'argon', }; // 系统自动推断为Map<int,String>类型 var gifts = Map(); // 通过实例化Map类创建 gifts['first'] = 'partridge'; // 通过map[key]访问或设置元素
- 4.3 Set
// Set是在Map的基础上进行扩展的,所以需要使用“<Type>”特别声明类型 var names = <String>{}; // 形式一 Set<String> names = {}; // 形式二 // 不特别声明类型则默认为Map类 var names = {}; // 这样会创建一个 Map ,而不是 Set 。
- 4.4 Rune
- 作用 Dart中
String
类使用UTF-16进行编码,但这种字符集能够表示的字符数量有限,所以Dart
中使用Rune
类来表示更多字符如emoji
表情等。
- 编码: 全世界存在各种各样的符号如‘a’、'我’及emoji表情,所以为了让计算机识别种类繁多的字符,需要用独一无二的二进制串标记这个字符。
- 字符集: 编码的字符越多需要的位数越多,但是部分应用可能仅在某个国家使用,不需要使用到他国的字符,所以不需要对其他国家的字符进行编码。因此为了节省资源就出现了字符集。字符集仅对部分字符进行编码,不同的地区使用不同的字符集。
Rune
用来表示字符串中的UTF-32
编码字符,使用如\uXXXX
的形式,其中的XXXX
代表4个16进制。如果还不够表示则用\u{大于4个X}
共6位。Runes input = new Runes( '\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}'); // 输出结果是:♥ 😅 😎 👻 🖖 👍
- 作用 Dart中
5.运算符
- 5.1 算术运算符 Dart中大部分运算符与Java类似,不同的是
- / 在Dart中
/
求出的结果是double
类型。 - ~/ 在Dart中
~/
求出的结果int
类型,对应Java
中的/
运算符。
- / 在Dart中
- 5.2 关系运算符
- 判断两个变量是否指向同一对象 Java中使用
==
符号;Dart使用identical(Object a, Object b)
方法,该方法属于dart:core
包。 - == Dart中使用
==
符号比较两个变量的是否相等,要想使用这个符号,需要在类中重写==
运算符。
- 判断两个变量是否指向同一对象 Java中使用
- 5.3 类型运算符
- is 判断一个变量是否属于一个类。如果变量为
null
或不属于该类则为false
,否则返回true并在该作用域内将该变量智能的转化为该类的实例如:if (emp is Person) { // emp已经默认转为Person类的实例 emp.firstName = 'Bob'; }
- !is 判断一个变量是否不属于一个类,不属于则为
true
- as 将一个变量强行转为该类,如果变量为
null
或不属于该类型则抛出异常(emp as Person).firstName = 'Bob';
- is 判断一个变量是否属于一个类。如果变量为
- 5.4 赋值运算符
- ??= Dart中除了常规的
=
赋值运算符外,还有??=
运算符,该运算符只有在左边变量为null
时,才会将右边的值赋给左边变量。 - 复合赋值运算符 如Java中的
+=
赋值运算符在Dart中同样适用
- ??= Dart中除了常规的
- 5.5 逻辑运算符 如
&&
、||
等基本与Java中一样 - 5.6 按位和位移运算符 如
&(与运算符)
、|(或运算符)
等基本与Java中一样 - 5.7 条件表达式 Dart中除了有三目条件表达式
exper ? trueExper : falseExper
外,还有- exper1 ?? exper2
exper1
不为null
则执行并返回exper1
,exper1
为null
则执行并返回exper2
- exper1 ?? exper2
- 5.8 级联运算符 Dart中的级联运算符有点类似Kotlin中的作用域函数
- 可以对同一个对像进行一系列的操作如调用函数、 访问对象的字段属性,每句代码执行后的返回值会被忽略。
querySelector('#confirm') // 获取对象。 ..text = 'Confirm' // 调用成员变量。 ..classes.add('important') ..onClick.listen((e) => window.alert('Confirmed!'));
- 级联的代码可以嵌套
final addressBook = (AddressBookBuilder() ..name = 'jenny' ..email = 'jenny@example.com' ..phone = (PhoneNumberBuilder() ..number = '415-555-0100' ..label = 'home') .build()) .build();
- 切记级联的符号是两个点不是一个点。错误示范如下:
var sb = StringBuffer(); sb.write('foo') // 少写了一个点,导致错误 ..write('bar'); // Error: 'void' 没有定义 'write' 函数。
- 可以对同一个对像进行一系列的操作如调用函数、 访问对象的字段属性,每句代码执行后的返回值会被忽略。
- 5.9 其他运算符
- ?. Dart与Kotlin类似有一个空安全访问符号。如例子
foo?.bar
,如果foo
不为null
才会访问bar
属性,如果为null
则不访问,以此来避免NPE。
- ?. Dart与Kotlin类似有一个空安全访问符号。如例子
万水千山总是情,麻烦手下别留情。
如若讲得有不妥,文末留言告知我,
如若觉得还可以,收藏点赞要一起。