作者:opLW
目录
1.变量
2.常量
3.内建类型
4.集合
5.运算符
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
代替。
- 1.4 变量的实例化
- 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 变量只能被设置一次。
- 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中使用
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}');
// 输出结果是:♥ 😅 😎 👻 🖖 👍
5.运算符
- 5.1 算术运算符 Dart中大部分运算符与Java类似,不同的是
- / 在Dart中
/
求出的结果是double
类型。 - ~/ 在Dart中
~/
求出的结果int
类型,对应Java
中的/
运算符。
- 5.2 关系运算符
- 判断两个变量是否指向同一对象 Java中使用
==
符号;Dart使用identical(Object a, Object b)
方法,该方法属于dart:core
包。 - == Dart中使用
==
符号比较两个变量的是否相等,要想使用这个符号,需要在类中重写==
运算符。
- 5.3 类型运算符
- is 判断一个变量是否属于一个类。如果变量为
null
或不属于该类则为false
,否则返回true并在该作用域内将该变量智能的转化为该类的实例如:
if (emp is Person) {
// emp已经默认转为Person类的实例
emp.firstName = 'Bob';
}
- !is 判断一个变量是否不属于一个类,不属于则为
true
- as 将一个变量强行转为该类,如果变量为
null
或不属于该类型则抛出异常
(emp as Person).firstName = 'Bob';
- 5.4 赋值运算符
- ??= Dart中除了常规的
=
赋值运算符外,还有??=
运算符,该运算符只有在左边变量为null
时,才会将右边的值赋给左边变量。 - 复合赋值运算符 如Java中的
+=
赋值运算符在Dart中同样适用
- 5.5 逻辑运算符 如
&&
、||
等基本与Java中一样 - 5.6 按位和位移运算符 如
&(与运算符)
、|(或运算符)
等基本与Java中一样 - 5.7 条件表达式 Dart中除了有三目条件表达式
exper ? trueExper : falseExper
外,还有
- exper1 ?? exper2
exper1
不为null
则执行并返回exper1
,exper1
为null
则执行并返回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。
万水千山总是情,麻烦手下别留情。
如若讲得有不妥,文末留言告知我,
如若觉得还可以,收藏点赞要一起。