现在位置: 首页 > Dart 教程 > 正文

Dart 运算符

运算符是程序中执行计算、比较和逻辑判断的符号。

本章系统介绍 Dart 中的各类运算符,包括算术、关系、逻辑、赋值、条件运算符以及类型检测。


算术运算符

算术运算符用于执行基本的数学运算。

实例

void main() {
  int a = 10;
  int b = 3;

  print('a = $a, b = $b');
  print('加法 a + b = ${a + b}');    // 13
  print('减法 a - b = ${a - b}');    // 7
  print('乘法 a * b = ${a * b}');    // 30
  print('除法 a / b = ${a / b}');    // 3.333... (结果是 double)
  print('整除 a ~/ b = ${a ~/ b}');  // 3 (取整,舍去小数)
  print('取余 a % b = ${a % b}');    // 1 (取模运算)
  print('取反 -a = ${-a}');          // -10 (一元负号)
}
a = 10, b = 3
加法 a + b = 13
减法 a - b = 7
乘法 a * b = 30
除法 a / b = 3.3333333333333335
整除 a ~/ b = 3
取余 a % b = 1
取反 -a = -10

注意:/ 运算符始终返回 double 类型,即使两个操作数都是 int 且能整除。如果只需要整数结果,使用 ~/ 整除运算符。

自增自减运算符

和大多数 C 系语言一样,Dart 支持 ++(自增)和 --(自减)。

实例

void main() {
  int count = 0;

  // 前置 ++:先自增,再使用
  print('前置 ++: ${++count}');  // 1

  // 后置 ++:先使用,再自增
  print('后置 ++: ${count++}');  // 1(此时 count 还是 1)
  print('现在 count = $count');   // 2

  // 自减同理
  print('前置 --: ${--count}');  // 1
  print('后置 --: ${count--}');  // 1
  print('现在 count = $count');   // 0
}
前置 ++: 1
后置 ++: 1
现在 count = 2
前置 --: 1
后置 --: 1
现在 count = 0

前置和后置的自增/自减在单独使用时效果一样,但在表达式中行为不同。建议初学者尽量避免在表达式中使用它们,单独写一行更清晰。


关系运算符

关系运算符用于比较两个值,结果是一个 bool 值。

运算符含义示例结果
==等于5 == 5true
!=不等于5 != 3true
>大于5 > 3true
<小于5 < 3false
>=大于等于5 >= 5true
<=小于等于3 <= 5true

实例

void main() {
  int runoobScore = 95;
  int passLine = 60;

  print('分数: $runoobScore, 及格线: $passLine');
  print('及格了吗? ${runoobScore >= passLine}');
  print('满分了吗? ${runoobScore == 100}');

  // 字符串也可以比较
  String a = 'apple';
  String b = 'banana';
  print("'$a' == '$b'? ${a == b}");

  // == 判断的是值是否相等
  String c = 'RUNOOB';
  String d = 'RUNOOB';
  print("'$c' == '$d'? ${c == d}");  // true(内容相同)
}
分数: 95, 及格线: 60
及格了吗? true
满分了吗? false
'apple' == 'banana'? false
'RUNOOB' == 'RUNOOB'? true

Dart 中 == 比较的是两个对象的值是否相等,而不是引用地址。这和 Java 不同——在 Dart 中你不需要用 equals() 方法来比较字符串。


逻辑运算符

逻辑运算符用于组合多个 bool 表达式,通常用于条件判断。

运算符含义说明
&&逻辑与两边都为 true 才返回 true
||逻辑或任意一边为 true 就返回 true
!逻辑非取反,true 变 false,false 变 true

实例

void main() {
  bool isLoggedIn = true;
  bool isAdmin = false;

  // && 与:两者都为 true
  print('登录且是管理员: ${isLoggedIn && isAdmin}');  // false

  // || 或:至少一个为 true
  print('登录或是管理员: ${isLoggedIn || isAdmin}');  // true

  // ! 非:取反
  print('未登录: ${!isLoggedIn}');  // false

  // 短路求值:如果左边已经能确定结果,右边不会执行
  int age = 20;
  // age > 18 已经是 true,但还需要看右边
  print('成年且有权限: ${age >= 18 && isAdmin}');

  // age < 18 已经是 false,&& 右边直接跳过
  print('未成年且有权限: ${age < 18 && isAdmin}');
}
登录且是管理员: false
登录或是管理员: true
未登录: false
成年且有权限: false
未成年且有权限: false

Dart 使用短路求值(Short-circuit Evaluation):对于 &&,如果左边为 false,右边不再计算;对于 ||,如果左边为 true,右边不再计算。

这个特性可以用来避免空指针问题。

实例

短路求值的实际应用:

void main() {
  String? username;

  // 安全判断:username 不为 null 且长度大于 3
  // 如果 username 为 null,&& 右边不会执行,避免了空指针错误
  if (username != null && username.length > 3) {
    print('有效用户名');
  } else {
    print('用户名无效或太短');
  }
}
用户名无效或太短

赋值运算符

基本的赋值运算符 = 你已经很熟悉了。

Dart 还提供了复合赋值运算符,简化常见的"计算后赋值"操作。

运算符等价写法示例(a=10 时)
+=a = a + ba += 3 → 13
-=a = a - ba -= 3 → 7
*=a = a * ba *= 3 → 30
/=a = a / ba /= 2 → 5.0
~/=a = a ~/ ba ~/= 3 → 3
%=a = a % ba %= 3 → 1

实例

void main() {
  int score = 0;

  // 每次答对加 10 分
  score += 10;
  print('答对第1题: $score');

  score += 10;
  print('答对第2题: $score');

  // 答错扣 5 分
  score -= 5;
  print('答错1题: $score');

  // 得分翻倍
  score *= 2;
  print('奖励翻倍: $score');

  print('RUNOOB 最终得分: $score');
}
答对第1题: 10
答对第2题: 20
答错1题: 15
奖励翻倍: 30
RUNOOB 最终得分: 30

条件运算符:?? 与 ??=

这两个运算符专为处理 null 值设计,是 Dart 空安全体系的重要组成部分。

?? 空值合并运算符

如果左侧表达式不为 null,返回左侧的值;否则返回右侧的值。

??= 空值赋值运算符

如果变量当前为 null,则赋值为右侧的值;否则保持不变。

实例

void main() {
  // ?? 空值合并
  String? nickname;
  String displayName = nickname ?? 'RUNOOB 用户';
  print(displayName);  // RUNOOB 用户

  nickname = '小R';
  displayName = nickname ?? 'RUNOOB 用户';
  print(displayName);  // 小R

  // 链式 ?? 也可以
  String? a;
  String? b;
  String result = a ?? b ?? '默认值';
  print(result);  // 默认值

  // ??= 空值赋值
  int? count;
  count ??= 0;  // count 为 null,赋值为 0
  print(count);  // 0

  count ??= 100;  // count 已经是 0(非 null),不赋值
  print(count);  // 0(不变)
}
RUNOOB 用户
小R
默认值
0
0

三元条件运算符 ? :

这是 Dart 唯一的三个操作数的运算符,是 if-else 的简洁版。

实例

void main() {
  int score = 75;

  // 语法:条件 ? 为真时的值 : 为假时的值
  String result = score >= 60 ? '及格' : '不及格';
  print('RUNOOB 考试结果: $result');

  // 可以嵌套使用(但不建议超过两层,可读性会变差)
  String grade = score >= 90 ? '优秀' : score >= 60 ? '及格' : '不及格';
  print('评级: $grade');
}
RUNOOB 考试结果: 及格
评级: 及格

类型检测运算符:is 与 as

is 用于检查对象是否属于某个类型,as 用于类型转换。

实例

void main() {
  // is:类型检查
  var name = 'RUNOOB';
  print('name 是 String 吗? ${name is String}');   // true
  print('name 是 int 吗? ${name is int}');         // false

  // is!:不是某类型
  print('name 不是 int 吗? ${name is! int}');      // true

  // as:类型转换
  Object obj = 'Hello, Dart!';
  // 将 Object 类型转换为 String,以便使用 String 的方法
  String str = obj as String;
  print(str.toUpperCase());

  // 安全的类型判断 + 转换
  Object maybeString = 42;
  if (maybeString is String) {
    // 在 is 判断为 true 的分支中,变量自动"提升"为该类型
    print(maybeString.length);  // 不需要 as 转换
  } else {
    print('不是字符串,值是: $maybeString');
  }
}
name 是 String 吗? true
name 是 int 吗? false
name 不是 int 吗? true
HELLO, DART!
不是字符串,值是: 42

优先使用 is 进行类型判断。在 is 为 true 的条件分支内,Dart 会自动将变量提升为目标类型(Type Promotion),无需再使用 as 强转。as 只在"你确定类型但编译器无法推断"时使用。


运算符优先级总览

当一个表达式中有多个运算符时,Dart 按照优先级从高到低依次计算。

如果不确定优先级,最稳妥的做法是使用括号明确计算顺序

优先级运算符说明
最高() [] . ?.括号、下标、成员访问
! ~ - ++ --一元运算符
* / % ~/乘除取余
+ -加减
< <= > >=关系比较
== !=相等判断
&&逻辑与
||逻辑或
??空值合并
? :三元条件
= += -= *= 等赋值(最低)

实例

void main() {
  // 不依赖优先级——用括号明确表达意图
  int result = ((10 + 5) * 2) - (8 ~/ 3);
  print('计算结果: $result');  // 28

  // 如果不加括号,结果可能完全不同
  // 10 + 5 * 2 - 8 ~/ 3 的结果会是 18(先乘除后加减)
  int result2 = 10 + 5 * 2 - 8 ~/ 3;
  print('不加括号: $result2');  // 18
}
计算结果: 28
不加括号: 18