运算符

Dart 定义了下表中显示的运算符 可以重载其中的许多运算符 请参考 可重载的运算符

Description (简介)Operator (运算符)
unary postfixexpr++    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??
conditionalexpr1 ? 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 (含义)
++varvar = var + 1 (表达式的值 = var + 1)
var++var = var + 1 (表达式的值 = var)
−−varvar = 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 isis! 运算符在运行时用来检查类型非常方便

Operator (运算符)Meaning (含义)
asTypecast(也用于指定库前缀)
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