运算符在编程语言中也是很重要的一环,如果有其他语言基础的话看这一节会很轻松,但是也要特别注意一些运算符,因为它跟其他语言还是有点差别的。
在运算符表 中,运算符的优先级按先后排列,即第一行优先级最高,最后一行优先级最低,而同一行中,最左边的优先级最高,最右边的优先级最低。
描述 | 运算符 |
---|---|
一元后缀 | 表达式++ 表达式-- () [] . ?. |
一元前缀 | -表达式 !表达式 ~表达式 ++表达式 --表达式 |
乘除法 | * / % ~/ |
加减法 | + - |
位运算 | << >> >>> |
二进制与 | & |
二进制异或 | ^ |
二进制或 | | |
关系和类型测试 >= > <= < as is is!
相等判断 == !=
逻辑与 &&
逻辑或 ||
空判断 ??
条件表达式 表达式 1 ? 表达式 2 : 表达式 3
级联 …
赋值 = *= /= += -= &= ^= 等等……
一旦你使用了运算符,就创建了表达式。
a++
a + b
a = b
a == b
c ? a : b
a is T
// 括号提高了可读性。
if ((n % i == 0) && (d % i == 0)) ...
// 难以理解,但是与上面的代码效果一样。
if (n % i == 0 && d % i == 0) ...
算术运算符
Dart 支持常用的算术运算符:
描述 | 运算符 |
---|---|
+ | 表达式++ 表达式-- () [] . ?. |
– | 减 |
-表达式 | 一元负, 也可以作为反转(反转表达式的符号) |
* | 乘 |
/ | 除 |
~/ | 除并取整 |
% | 取模 |
示例:
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // 结果是一个浮点数
assert(5 ~/ 2 == 2); // 结果是一个整数
assert(5 % 2 == 1); // 取余
assert('5/2 = ${5 ~/ 2} r ${5 % 2}' == '5/2 = 2 r 1');
Dart 还支持自增自减操作。
++var
var = var + 1 (表达式的值为 var + 1)
var++ var = var + 1 (表达式的值为 var)
--var var = var – 1 (表达式的值为 var – 1)
var-- var = var – 1 (表达式的值为 var)
示例:
var a, b;
a = 0;
b = ++a; // 在 b 赋值前将 a 增加 1。
assert(a == b); // 1 == 1
a = 0;
b = a++; // 在 b 赋值后将 a 增加 1。
assert(a != b); // 1 != 0
a = 0;
b = --a; // 在 b 赋值前将 a 减少 1。
assert(a == b); // -1 == -1
a = 0;
b = a--; // 在 b 赋值后将 a 减少 1。
assert(a != b); // -1 != 0
关系运算符
== 相等
!= 不等
> 大于
< 小于
>= 大于等于
<= 小于等于
要判断两个对象 x 和 y 是否表示相同的事物使用 == 即可。
== 运算符的一些规则:
1.假设有变量 x 和 y,且 x 和 y 至少有一个为 null,则当且仅当 x 和 y 均为 null 时 x == y 才会返回 true,否则只有一个为 null 则返回 false。
2.x.==(y) 将会返回值,这里不管有没有 y,即 y 是可选的。也就是说 == 其实是 x 中的一个方法,并且可以被重写。
下面的代码给出了每一种关系运算符的示例:
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);
类型判断运算符
as //类型转换(也用作指定类前缀))
is //如果对象是指定类型则返回 true
is! //如果对象是指定类型则返回 false
当且仅当 obj 实现了 T 的接口,obj is T 才是 true。例如 obj is Object 总为 true,因为所有类都是 Object 的子类。
使用 as 操作符可以把对象转换为特定的类型。一般情况下可以将其当做 is 判定类型后调用所判定对象的函数的缩写形式。假设有如下代码:
if (emp is Person) {
// 类型检查
emp.firstName = 'Bob';
}
你可以使用 as 运算符进行缩写:
(emp as Person).firstName = 'Bob';
tips:上述两种方式是有区别的:如果 emp 为 null 或者不为 Person 类型,则第一种方式最多只是不执行条件内代码,但是第二种方式则会抛出异常。
赋值运算符
可以使用 = 来赋值,同时也可以使用 ??= 来为值为 null 的变量赋值。
// 将 value 赋值给 a
a = value;
// 当且仅当 b 为 null 时才赋值
b ??= value;
像 += 这样的赋值运算符将算数运算符和赋值运算符组合在了一起。
= –= /= %= >>= ^=
+= *= ~/= <<= &= |=
下表解释了符合运算符的原理:
场景 复合运算 等效表达式
假设有运算符 op: a op= b a = a op b
示例: a += b a = a + b
下面的例子展示了如何使用赋值以及复合赋值运算符:
var a = 2; // 使用 = 赋值
a *= 3; // 赋值并做乘法运算:a = a * 3
assert(a == 6);
逻辑运算符
使用逻辑运算符你可以反转或组合布尔表达式。
运算符 描述
!!表达式 对表达式结果取反(即将 true 变为 false,false 变为 true)
|| 逻辑或
&& 逻辑与
下面是使用逻辑表达式的示例:
if (!done && (col == 0 || col == 3)) {
// ...Do something...
}
按位和移位运算符
在 Dart 中,二进制位运算符可以操作二进制的某一位,但仅适用于整数。
运算符 描述
& 按位与
| 按位或
^ 按位异或
~表达式 按位取反
<< 左位移
>> 右位移
下面是使用按位和移位运算符的示例:
final value = 0x22;
final bitmask = 0x0f;
assert((value & bitmask) == 0x02); // 按位与
assert((value & ~bitmask) == 0x20); // 取反后按位与
assert((value | bitmask) == 0x2f); // 按位或
assert((value ^ bitmask) == 0x2d); // 按位异或
assert((value << 4) == 0x220); // 位左移
assert((value >> 4) == 0x02); // 位右移
条件表达式
Dart 有两个特殊的运算符可以用来替代 if-else 语句:
condition ? expr1 : expr2 //条件 ? 表达式 1 : 表达式 2:如果条件为 true,执行表达式 1并返回执行结果,否则执行表达式 2 并返回执行结果。
expr1 ?? expr2表达式 1 ?? 表达式 2:如果表达式 1 为非 null 则返回其值,否则执行表达式 2 并返回其值。
如果赋值是根据布尔表达式则考虑使用 ?:。
var visibility = isPublic ? 'public' : 'private';
如果赋值是根据判定是否为 null 则考虑使用 ??。
String playerName(String name) => name ?? 'Guest';
上述示例还可以写成至少下面两种不同的形式,只是不够简洁:
// 相对使用 ?: 运算符来说稍微长了点。
String playerName(String name) => name != null ? name : 'Guest';
// 如果使用 if-else 则更长。
String playerName(String name) {
if (name != null) {
return name;
} else {
return 'Guest';
}
}
级联运算符(…)
级联运算符(…)可以让你在同一个对象上连续调用多个对象的变量或方法。
比如下面的代码:
querySelector('#confirm') // 获取对象。
..text = 'Confirm' // 使用对象的成员。
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
第一个方法 querySelector 返回了一个 Selector 对象,后面的级联操作符都是调用这个 Selector 对象的成员并忽略每个操作的返回值。
上面的代码相当于:
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
级联运算符可以嵌套,例如:
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = '[email protected]'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
在返回对象的函数中谨慎使用级联操作符。例如,下面的代码是错误的:
var sb = StringBuffer();
sb.write('foo')
..write('bar'); // 出错:void 对象中没有方法 write。
上述代码中的 sb.write() 方法返回的是 void,返回值为 void 的方法则不能使用级联运算符。
tips:严格来说 … 级联操作并非一个运算符而是 Dart 的特殊语法。结语:
最近在录制视频,到时候也会免费放在公众号中供大家学习交流使用。如果对您有用请关注,如果文中有错也欢迎指正。共同学习,共同进步。