运算符
Dart 定义了下表中显示的运算符 可以重载其中的许多运算符 请参考 可重载的运算符
Description (简介) | Operator (运算符) |
---|---|
unary postfix | expr++ expr-- () [] . ?. |
unary prefix | -expr !expr ~expr ++expr --expr |
multiplicative | * / % ~/ |
additive | + - |
shift | << >> >>> |
bitwise AND | & |
bitwise XOR | ^ |
bitwise OR | | |
relational and type test | >= > <= < as is is! |
equality | == != |
logical AND | && |
logical OR | || |
if null | ?? |
conditional | expr1 ? expr2 : expr3 |
cascade | . . |
assignment | = *= /= += -= &= ^= etc. |
警告:运算符优先级请查阅 Dart语言规范
使用运算符时即创建表达式 运算符表达式 示例:
a++a + ba = ba == bc ? a : ba is T123456
在运算符表中 每个运算符的优先级都比其后面各行中的运算符高
如 乘法运算符 % 的优先级高于相等运算符
== 其优先级高于逻辑运算符 &&
该优先级意味着以下两行代码以相同的方式执行:
// Parentheses improve readability.if ((n % i == 0) && (d % i == 0)) ...// Harder to read, but equivalent.if (n % i == 0 && d % i == 0) ...12345
算术运算符
Operator (运算符) | Meaning (含义) |
---|---|
+ | 加 |
– | 减 |
-expr | 一元减号 也称之为负号(反转表达式符号) |
* | 乘 |
/ | 除 |
~/ | 取商(整数结果) |
% | 取模(余数的整数结果) |
示例:
assert(2 + 3 == 5);assert(2 - 3 == -1);assert(2 * 3 == 6);assert(5 / 2 == 2.5); // Result is a doubleassert(5 ~/ 2 == 2); // Result is an intassert(5 % 2 == 1); // Remainderassert('5/2 = ${5 ~/ 2} r ${5 % 2}' == '5/2 = 2 r 1');12345678
Dart 还支持前缀和后缀的增量和减量运算符
Operator (运算符) | Meaning (含义) |
---|---|
++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; // Increment a before b gets its value.assert(a == b); // 1 == 1a = 0;b = a++; // Increment a AFTER b gets its value.assert(a != b); // 1 != 0a = 0;b = --a; // Decrement a before b gets its value.assert(a == b); // -1 == -1a = 0;b = a--; // Decrement a AFTER b gets its value.assert(a != b); // -1 != 01234567891011121314151617
平等与关系运算符
下表中列出了相等运算符和关系运算符的含义
Operator (运算符) | Meaning (含义) |
---|---|
== | 等于 |
!= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
要测试两个对象 X 和 Y是否相等 使用 == 运算符在极少数情况下 需要知道两个对象是否是完全相同的对象 使用 identical() 函数运算符的使用方式 :
assert(2 == 2);assert(2 != 3);assert(3 > 2);assert(2 < 3);assert(3 >= 3);assert(2 <= 3);123456
类型测试运算符
as is 和 is! 运算符在运行时用来检查类型非常方便
Operator (运算符) | Meaning (含义) |
---|---|
as | Typecast(也用于指定库前缀) |
is | 如果检验对象是指定的类型 则返回 True |
is! | 如果检验对象非指定的类型 则返回 True |
如果 obj 是由 T 的接口实现的 那么表达式obj is T则返回 True
如:obj is Object 总是返回 True
使用 as 运算符将对象转换为特定类型一般情况下 应将其用在检测对象语句的简写 例如:
if (emp is Person) {// Type checkemp.firstName = 'Bob';}1234
使用 as 运算符可以缩短代码:
(emp as Person).firstName = 'Bob';1
如果 emp 为 null 或者不是 Person 则第一个示例不执行任何操作 而第二个示例则会引发异常
赋值运算符
赋值号 = 运算符 对变量进行赋值 在变量为原本为 null 的情况下赋值则需要使用 ??= 运算符
// Assign value to aa = value;// Assign value to b if b is null; otherwise, b stays the sameb ??= value;1234
复合赋值运算符 将运算与赋值结合在一起
= | –= | /= | %= | >>= | ^= |
---|---|---|---|---|---|
+= | *= | ~/= | <<= | &= | |= |
逻辑运算符的示例:
if (!done && (col == 0 || col == 3)) {// ...Do something...}123
按位和移位运算符
Operator (运算符) | Meaning (含义) |
---|---|
& | 与 |
|| | 或 |
^ | 异或 (同为 0 异为 1) |
~expr | 一元按位补码(0变为1 1变为0) |
<< | 往左位移 |
>> | 往右位移 |
使用按位和移位运算符的示例:
final value = 0x22;final bitmask = 0x0f;assert((value & bitmask) == 0x02); // ANDassert((value & ~bitmask) == 0x20); // AND NOTassert((value | bitmask) == 0x2f); // ORassert((value ^ bitmask) == 0x2d); // XORassert((value << 4) == 0x220); // Shift leftassert((value >> 4) == 0x02); // Shift right123456789
条件表达式
Dart 有两种条件运算符 在使用 if-else 表达式时更方便:
condition ? expr1 : expr2// 如果条件为真 则结果为(返回) expr1 否则结果为 expr212
expr1 ?? expr2// 如果 expr1 非空则结果为(返回) expr1 否则结果为 expr212
如果需要基于布尔表达式来判断分配值时 使用 condition ? expr1 : expr2
var visibility = isPublic ? 'public' : 'private';1
如果布尔表达式的结果为 null 请考虑使用 expr1 ?? expr2
String playerName(String name) => name ?? 'Guest';1
前面的示例至少可以用两种其它其他方式编写 但不那么简洁:
// Slightly longer version uses ?: operator.String playerName(String name) => name != null ? name : 'Guest';// Very long version uses if-else statement.String playerName(String name) {if (name != null) {return name;} else {return 'Guest';}}1234567891011
级联符号
级联(..)同一对象执行系列操作除了函数调用
访问同一对象上的字段
节省创建临时变量的步骤
编写更多流畅的代码
querySelector('#confirm') // Get an object...text = 'Confirm' // Use its members...classes.add('important')..onClick.listen((e) => window.alert('Confirmed!'));1234
第一个方法调用 querySelector() 返回选择器的对象 遵循级联表示法的代码在此选择器对象上运行 而忽略了可能返回的其它后续值
等效于:
var button = querySelector('#confirm');button.text = 'Confirm';button.classes.add('important');button.onClick.listen((e) => window.alert('Confirmed!'));1234
也可以嵌套级联 例如:
final addressBook = (AddressBookBuilder()..name = 'jenny'..email = 'jenny@example.com'..phone = (PhoneNumberBuilder()..number = '415-555-0100'..label = 'home').build()).build();12345678
在返回实际对象的函数上构造级联 例如以下的错误代码:
var sb = StringBuffer();sb.write('foo')..write('bar'); // Error: method 'write' isn't defined for 'void'.123
因为不能在 void 上构建级联 所以sb.write() 调用返回 void 在此处构建级联所以错误
提示: 严格来说 级联的 “双点” 符号不是运算符它只是Dart语法的一部分
Dart支持.操作符调用对象的方法
但 Dart 另外增加了一种级联运算符.. 用两个点表示
级联运算符可在同一个对象上连续调用多个方法及访问成员变量
..可避免创建临时变量 代码更流畅
如类Person有三个方法 setName、setAge、save 可调用
new Person()..setName("Bob")..setAge(20)..save();
使用级联运算符调用方法
无需该方法返回对象本身即可连续的流式的调用该对象的其他方法
条件成员访问符
Java空指针错误
因此在方法调用前需要进行对象的非空判断
判断语句使代码冗长 可读性差
Dart 发明了新的运算符用于处理此类情况
条件成员访问符?.
和.类似 但运算符左边的对象不能为null
否则返回null
若对象不为null 则返回对象本身
// list1默认值为null
List list1;
print(list1?.length); // null
List list2 = [];
print(list2?.length); // 0
其它运算符
在其他示例中 我们已经认识了大多数的运算符 接下来我们展示剩下的一些运算符:
Operator (运算符) | Name(名称) | Meaning (含义) |
---|---|---|
() | Function application | 代表一个函数调用 |
[] | List access | 引用列表中指定索引处的值 |
. | Member access | 引用表达式的属性 例如 foo.bar 意思是从表达式 foo 中选择其属性 bar |
?. | Conditional member access | 类似于 ., 但是最左边的操作数可以为 null; 例如 foo?.bar 意思是从表达式 foo 中选择属性bar 除非 foo 为 null(在这种情况下 foo?.bar 的值为 null) |
有关 (.,|?.|..) 的更多信息 请参见 Classes
尊贵的董事大人
英文标题不为空时 视为本栏投稿
需要关键字 描述 英文标题