操作符

计算机程序的表达式由操作符和操作数构成。如1+2这个表达式中,+是操作符,数字12是操作数。如果表达式中只有一个操作数,它便是一元表达式;如果有两个操作数,它便是二元表达式;类似地还有三元表达式。一元表达式中的操作符为一元操作符。

Dart提供了非常丰富的操作符,且支持为类(class,第4-5章内容)定义操作符。

在算数表达式中(例如 2 + 3 × 5),乘除法的优先级高于加减法,因此优先计算乘除法( 3 × 5),但可以通过圆括号来改变求值顺序(例如 (2 + 3) × 5)操作符的优先级,与算术中加减乘除的优先级类似。

算术操作符

操作符含义示例
+1 + 2 //3
-4 - 3 //1
-expr符号取反-x
*3 * 5 //15
/除,结果是一个浮点数7 / 2 //3.5
~/整除,除法的整数部分,结果是一个整数7 ~/ 2 //3
%模,除法的余数部分,结果是一个整数或浮点数7 % 2 //1

Dart支持自增(++)与自减(--)一元操作符。表达式x++ 相当于x = x+1x-- 相当于x = x-1。 这两个操作符位于操作数之前或之后均可,但有区别。

// ch0105_1.dart
void main() {
  var x = 3, y = 3;
  print('${x++} $x'); // Output: 3 4
  print('${++y} $y'); // Output: 4 4
}

表达式x++ 的值为x,先返回x,再将x自增1;而表达式++x的值为x+1,也就是先将x自增1,再返回x。 我们用同样的方式去理解x----x

关系操作符

关系操作符用于布尔表达式(其结果为truefalse)。

操作符含义示例
==等于5 == 5
!=不等于6 != 7
>大于8 > 7
<小于6 < 9
>=大于等于4 >= 3
<=小于等于3 <= 4

关于== 操作符:

  1. 如果 xynull,则只有当它们都是 nullx==y 才返回 true;如果只有一个为 null,则x==y 返回 false
  2. x == y本质上是调用 x== 操作符方法(以y作为参数),然后返回其结果, 类似于 x.equals(y)
  3. 极少情况下,你需要知道xy是否引用了同一个对象,使用identical(x,y)

NOTE: 方法、对象的概念将在第4章介绍。

类型测试操作符

asisis! 操作符用于在运行时检查类型。

操作符含义示例
as类型转换(该符号也用于import语句中给包取别名)obj as String
is如果对象具有指定类型返回trueobj is double
is!如果对象不具有指定类型返回trueobj is! num

赋值操作符

首先来看 =??= 这两个赋值操作符。

操作符含义示例
=赋值x = 123;
??=仅当变量为null才对其赋值 x ??= 234;

复合赋值操作符组合了一个操作和赋值,以 += 为例, x += y 就等价于 x = x + y。假设 op 是一个操作符,那么 a op= b 等价于 a = a op b。以下是复合赋值操作符:

*=%=>>>=^=
+=/=<<=&=
|=-=~/=>>=

逻辑操作符

您使用逻辑运算符反转或组合布尔表达式。

操作符含义示例
!expr逻辑非,逻辑取反!x
||逻辑或(OR)x == 3 || x ==4
&&逻辑与(AND) x >=1 && y < 6

下面是一个稍微复杂的例子:

if (ok && (x < 5 || y > 6)) {
    print('good');
}

位操作符

Dart可以对数字的每一位(bit)进行操作。

操作符含义示例
&与(AND) 1 & 2 //0
|或(OR)1 | 2 //3
^异或(XOR)2 ^ 3 //1
~expr按位补码(0变为1,1变为0)~1 //-2
<<左移位1 << 10 //1024
>>右移位1024 >> 9 //2
>>>无符号右移-1 >>> 61 //7

条件表达式

先来看下面的代码片段:

  int n;
  if (x < 3) {
    n = 3;
  } else {
    n = x;
  }

上面计算n 的代码,用条件表达式就简化为:

  var n = x < 3 ? 3 : x;

条件表达式 condition ? expr1 : expr2 ,有 ?:2个操作符,?之前为一个表示条件的布尔表达式condition;如果condition的值为true,该表达式的值就取expr1的值,否则取 expr2的值。

级联符号

Dart的级联符号(..?..)用于对同一个对象进行一系列操作。下面的代码片段:

  var sb = StringBuffer();
  sb.write('Hello ');
  sb.write('Dart');
  sb.write('!');
  print(sb);

用级联符号就简化为:

  print(
    StringBuffer()
      ..write('Hello ')
      ..write('Dart')
      ..write('!'),
  );

?....类似,只不过用于nullable对象的第一个操作。

  sb2
    ?..write('Hello ')
    ..write('Dart')
    ..write('!');

上面代码中的sb2如果是null,就不会执行任何的级联操作。

其他操作符

下面的操作符已在前面章节介绍过,不再赘述。

操作符含义示例
()函数调用doIt()
[]下标访问todoList[0]
?[]有条件下标访问fruits?[0]
.成员访问point.x
?.有条件成员访问point?.x
!非空断言point!
...展开一个集合(collection),插入另一个集合(collection)...myList
...?...类似,适用于nullable对象....?anotherList

操作符优先级

下表中的操作符按优先级从高到低排依次列,第一行中的优先级最高,第二行次之,以此类推; 同一行里的操作符具有相同的优先级。

描述操作符
一元后缀expr++   expr--   ()   []   ?[]   .   ?.   !
一元前缀-expr   !expr   ~expr   ++expr   --expr   await expr
乘除*   /   %   ~/
加减+   -
移位<<   >>   >>>
位与 AND&
位异或 XOR^
位或 OR|
关系及类型测试>=   >   <=   <   as   is   is!
相等==   !=
逻辑与 AND&&
逻辑或 OR||
if-null??
条件expr1 ? expr2 : expr3
级联..   ?..
赋值=   *=   /=   +=   -=   &=   ^=
展开...   ...?

参考资料