ZetCode

Dart 运算符

最后修改日期:2025 年 6 月 4 日

本教程将探讨 Dart 运算符,演示它们如何用于创建表达式来处理数据。

运算符 是一个符号,用于触发对其运算对象(operand)的特定操作。运算符在编程中模仿数学运算来操作数据。运算对象 是运算符的输入,通常是值或变量。

表达式结合了运算对象和运算符,运算符定义了要执行的操作。求值顺序由运算符的优先级结合性 决定,以确保结果可预测。

运算符根据其运算对象的数量进行分类。一元运算符 使用一个运算对象,而二元运算符 使用两个。有些运算符(如 +)是重载 的,可以根据上下文执行不同的任务(例如,对数字求和或连接字符串)。

Dart 负号运算符

负号运算符 - 用于否定一个值,反转其符号。

main.dart
void main() {
  int a = 1;

  print(-a);
  print(-(-a));
}

此示例展示了负号运算符如何否定一个值,然后将其值反转回原始符号。

$ dart main.dart
-1
1

Dart 赋值运算符

赋值运算符 = 将一个值存储到变量中。与数学中的 = 表示相等性不同,在编程中,它将右侧的值赋给左侧的变量。

int x = 1;

这会将值 1 赋给变量 x

x = x + 1;

这会将 x 增加 1,使得 x 等于 2。此类表达式在编程中是有效的,但在数学中则无效。

3 = x;

这是无效的,因为像 3 这样的字面量不能被赋值,这会导致语法错误。

Dart 的空感知赋值运算符 ??= 仅当变量为 null 时才为其赋值,从而确保安全初始化。

main.dart
void main() {
  int? x;
  x ??= 6;
  print(x);

  x ??= 3;
  print(x);
}

由于 x 最初为 null,因此将其赋值为 6。第二次赋值被忽略,因为 x 不再是 null

$ dart main.dart
6
6

Dart 递增和递减运算符

递增(++)和递减(--)运算符在变量上加 1 或减 1,提供了一种简洁的更新值的方法。

main.dart
void main() {
  var x = 6;

  x++;
  x++;

  print(x);

  x--;
  print(x);
}

此示例将 x 从 6 递增两次到 8,然后将其递减到 7,演示了这两种运算符。

$ dart main.dart
8
7

这些运算符可以是前缀或后缀,这会影响值相对于其使用的时间点进行更新,这可能导致行为上的细微差别。

main.dart
void main() {
  var r1 = increase(3);
  print(r1);

  var r2 = increase2(3);
  print(r2);
}

int increase(int x) {
  return ++x;
}

int increase2(int x) {
  return x++;
}

前缀 ++x 在返回之前递增,得到 4。后缀 x++ 在递增之前返回原始值,得到 3。

$ dart main.dart
4
3

Dart 复合赋值运算符

复合赋值运算符将运算与赋值结合起来,为常见的更新(如加法或乘法)提供了一种简写方式。

a = a + 3;
a += 3;

两个表达式都将 3 加到 a 上,其中 += 是简写形式。其他复合运算符包括 -=*=/=~/=%=&=|=^=<<=>>=

main.dart
void main() {
  var a = 1;
  a = a + 1;
  print(a);

  a += 5;
  print(a);

  a *= 3;
  print(a);
}

此示例显示了标准加法,然后是复合加法和乘法,最终 a 更新为 2、7 和 21。

$ dart main.dart
2
7
21

Dart 算术运算符

算术运算符对数字运算对象执行数学运算,包括加法、减法、乘法和除法。

符号名称
+加法
-减法
*乘法
/除法
~/整数除法
%余数

上表列出了 Dart 中的算术运算符

main.dart
void main() {
  var a = 10;
  var b = 11;
  var c = 12;
  var add = a + b + c;
  var sb = c - a;
  var mult = a * b;
  var div = c / 3;
  var rem = c % a;

  print(add);
  print(sb);
  print(mult);
  print(div);
  print(rem);
}

此示例演示了加法、减法、乘法、除法和取余运算,其中 % 计算模(例如,12 % 10 = 2)。

$ dart main.dart
33
2
110
4.0
2

/ 运算符返回一个 double,而 ~/ 返回一个整数,区分了浮点除法和整数除法。

main.dart
void main() {
  var c = 5 / 2;
  print(c);

  var d = 5 ~/ 2;
  print(d);
}

对于 5 除以 2,此示例显示 / 返回 2.5 (double),而 ~/ 返回 2 (integer)。

$ dart main.dart
2.5
2

Dart 布尔运算符

布尔运算符(也称为逻辑运算符)用于操作布尔值以控制程序流程,通常在条件语句中使用。

符号名称
&&逻辑与
||逻辑或
!否定

上表列出了 Dart 中的布尔运算符。

main.dart
void main() {
  var x = 3;
  var y = 8;

  print(x == y);
  print(y > x);

  if (y > x) {
    print("y is greater than x");
  }
}

此示例使用比较运算符生成布尔结果,这些结果控制 if 语句,在条件为真时打印消息。

$ dart main.dart
false
true
y is greater than x

仅当两个运算对象都为 true 时,逻辑 AND (&&) 运算符才返回 true。

main.dart
void main() {
  var a = true && true;
  var b = true && false;
  var c = false && true;
  var d = false && false;

  print(a);
  print(b);
  print(c);
  print(d);
}

这演示了 &&,只有第一种情况返回 true。

$ dart main.dart
true
false
false
false

只要至少一个运算对象为 true,逻辑 OR (||) 运算符就返回 true。

main.dart
void main() {
  var a = true || true;
  var b = true || false;
  var c = false || true;
  var d = false || false;

  print(a);
  print(b);
  print(c);
  print(d);
}

四种情况中有三种返回 true,因为只有两个运算对象都为 false 时结果才为 false。

$ dart main.dart
true
true
true
false

否定运算符 ! 用于反转布尔值。

main.dart
void main() {
  print(!true);
  print(!false);
  print(!(4 < 3));
}

这显示了 ! 将 true 转换为 false,并将一个表达式求值为 true。

$ dart main.dart
false
true
true

Dart 比较运算符

比较运算符(也称为关系运算符)用于比较值并返回布尔结果,这对于代码中的决策至关重要。

符号含义
<小于
<=小于或等于
>大于
>=大于或等于
==等于
!=不等于

上表列出了 Dart 中的比较运算符。

main.dart
void main() {
  print(3 < 4);
  print(3 == 4);
  print(4 >= 3);
  print(4 != 3);
}

此示例使用 == 运算符比较整数的相等性(与某些使用 = 的语言不同),返回布尔结果。

$ dart main.dart
true
false
true
true

Dart 按位运算符

按位运算符用于操作数字的二进制表示,执行逐位操作,这对于标志管理等底层任务很有用。

符号含义
&按位与
|按位或
^按位异或
~按位非
<<左移
>>右移

当两个对应位都为 1 时,按位 AND (&) 运算符才产生 1。

      00110
   &  00011
   =  00010

对于 6 (00110) 和 3 (00011),结果是 2 (00010)。

main.dart
void main() {
  print(6 & 3);
}
$ dart main.dart
2

如果任一位为 1,则按位 OR (|) 运算符产生 1。

      00110
   |  00011
   =  00111

对于 6 和 3,结果是 7 (00111)。

main.dart
void main() {
  print(6 | 3);
}
$ dart main.dart
7

如果只有一位为 1,则按位 XOR (^) 运算符产生 1。

      00110
   ^  00011
   =  00101

对于 6 和 3,结果是 5 (00101)。

main.dart
void main() {
  print(6 ^ 3);
}
$ dart main.dart
5

Dart 三元运算符

三元运算符 ?: 提供了一种简洁的条件表达式,它根据布尔条件评估两个表达式中的一个。

condition ? expr1 : expr2

如果条件为 true,则评估 expr1;否则,评估 expr2

main.dart
void main() {
  var age = 18;

  var isAdult = (age >= 18) ? true : false;

  if (isAdult) {
    print("he is adult");
  } else {
    print("he is minor");
  }
}

此示例使用三元运算符根据年龄设置 isAdult,然后使用 if 语句打印一条消息。

$ dart main.dart
he is adult

Dart 展开运算符

展开运算符 ... 将集合的所有元素插入到另一个集合中,从而简化列表、集合或映射的构建。

main.dart
void main() {
  var vals = [1, 2, 3];
  var vals2 = [...vals, 4, 5, 6];

  print(vals);
  print(vals2);
}

这会将 vals 展开到 vals2 中,添加更多元素以创建新列表。

$ dart main.dart
[1, 2, 3]
[1, 2, 3, 4, 5, 6]

Dart 级联运算符

级联运算符 .. 允许对同一对象执行多个操作,从而提高代码的流畅性和可读性。

main.dart
class User {
  var fname;
  var lname;
  var occupation;
  String toString() {
    return "$fname $lname is a $occupation";
  }
}

void main() {
  var u = User()
    ..fname = "John"
    ..lname = "Doe"
    ..occupation = "gardener";

  print(u);
}

此示例使用级联初始化 User 对象的属性,然后打印其字符串表示形式。

$ dart main.dart
John Doe is a gardener

Dart `is` 和 `is!` 运算符

isis! 运算符在运行时检查对象的类型,如果类型匹配或不匹配,则分别返回 true。

main.dart
class Base {}

class Derived extends Base {}

void main() {
  var b = Base();
  var d = Derived();

  print(d is Base);
  print(d is! Base);
  print(b is Derived);
  print(d is Object);
  print(d is! Object);
}

这会检查类型关系,显示继承和对象类型属性。

$ dart main.dart
true
false
false
true
false

Dart 空感知运算符

Dart 的空感知运算符(如 ????=)可以安全地处理 null 值,提供默认值或条件赋值以防止与 null 相关的错误。

main.dart
void main() {
  String? name;
  
  // Null-coalescing operator
  String displayName = name ?? "Guest";
  print(displayName);
  
  // Null-aware assignment
  name ??= "Anonymous";
  print(name);
  
  name ??= "User";
  print(name);
}

如果 name 为 null,则 ?? 运算符提供默认值;如果变量为 null,则 ??= 运算符为其赋值,否则保持不变。

$ dart main.dart
Guest
Anonymous
Anonymous

Dart 条件成员访问运算符

条件成员访问运算符 ?. 可以安全地访问对象的属性或方法,如果对象为 null,则返回 null,从而避免运行时错误。

main.dart
void main() {
  String? text;
  
  // Conditional member access
  int? length = text?.length;
  print(length);
  
  text = "Hello";
  length = text?.length;
  print(length);
}

这会安全地访问 length 属性,当 text 为 null 时返回 null,当不为 null 时返回实际长度。

$ dart main.dart
null
5

Dart 类型转换运算符

类型转换运算符 as 在运行时将对象转换为特定类型,如果转换无效则抛出异常,这对于使用动态类型或接口类型非常有用。

main.dart
void main() {
  var value = "Dart";
  
  // Type cast
  String text = value as String;
  print(text.toUpperCase());
  
  // Safe cast with is check
  if (value is String) {
    String safeText = value as String;
    print(safeText.length);
  }
}

这会将 value 转换为 String,允许进行特定于 String 的操作,并演示了带有类型检查的安全转换。

$ dart main.dart
DART
4

Dart 运算符优先级

运算符优先级决定了求值运算符的顺序,它解决了表达式中的歧义,以确保结果一致。

main.dart
void main() {
  print(3 + 5 * 6);
  print((3 + 5) * 6);

  print(!true || true);
  print(!(true || true));
}

乘法比加法具有更高的优先级,因此首先计算 5 * 6,得到 33。括号会覆盖此优先级,得到 48。否定优先于 ||,这会影响逻辑结果。

$ dart main.dart
33
48
true
false

Dart 运算符优先级表

下表列出了 Dart 中的运算符优先级,从最高到最低。优先级较高的运算符在优先级较低的运算符之前进行求值。同一行的运算符具有相等的优先级,并根据结合性规则进行求值。

优先级运算符描述
1 (最高)[], (), ., ?.成员访问、函数调用
2++, --, ~后缀递增/递减、按位非
3++, --, +, -, !前缀递增/递减、一元加/减、逻辑非
4*, /, %, ~/乘法
5+, -加法
6>>, <<按位移位
7>, <, >=, <=, is, is!关系、类型测试
8==, !=相等
9&按位与
10^按位异或
11|按位或
12&&逻辑与
13||逻辑或
14??空合并
15? :条件(三元)
16=, +=, -=, *=, /=, %=, ~/=, &=, |=, ^=, <<=, >>=, ??=赋值
17 (最低),逗号

请参考此表来理解 Dart 如何求值复杂表达式,并避免由于运算符优先级而产生意外结果。

结合性规则

结合性决定了相等优先级的运算符的求值顺序。大多数运算符(如 /*)是左到右的,而赋值和一元运算符是右到左的。

main.dart
void main() {
  print(9 / 3 * 3);

  var j = 0;
  j *= 3 + 1;
  print(j);
}

表达式 9 / 3 * 3 按从左到右的顺序计算为 (9 / 3) * 3,得到 9。复合赋值 *= 是从右到左的,因此先计算 3 + 1,然后将其乘以 j

$ dart main.dart
9.0
0

来源

Dart 运算符 - 语言参考

本教程涵盖了 Dart 运算符、它们在表达式中的作用以及优先级和结合性如何影响求值。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的经验。自 2007 年以来,我撰写了超过 1,400 篇文章和 8 本电子书,并拥有十多年的编程教学经验。

列出 所有 Dart 教程