
3.5 运算符
运算符,也称为操作符。Dart编程语言定义了很多运算符,如表3.2所示。
表3.2 Dart的运算符

所有带有运算符的都是表达式。在上述表格中,运算符的优先级顺序为从左到右,从上到下。对比下面两个表达式:

由于“%”的优先级高于“==”,且“==”的优先级高于“||”,因此上述代码运行后的结果如下:

要注意的是,对于有两个操作数的运算符,其功能取决于左侧的操作数。
3.5.1 算术运算符
算术运算符很好理解,和传统的数学意义最为类似。所有算术运算符如表3.3所示。
表3.3 算术运算符

如表3.3所示,加法、减法、乘法、除法、取反都很好理解。但在Dart中直接做除法时,如果不能整除,就不会只返回整数,而是自动转换为小数返回。如果要只取整数部分,就需要使用“~/”。具体的算术运算符示例如下所示:


运行结果如下:

和其他高级语言一样,Dart也支持变量自增/自减操作。经过自增操作,值比原来大1;经过自减操作,值比原来小1。我们会发现,自增和自减分别有两种不同的写法,那么它们的区别是什么呢?用下面的代码进行测试:

输出结果:

由此可见,++a立即见效,其表达式已经是自增之后的结果。而a++则不同,其表达式结果仍为原来的数值,在之后才会做加1的操作。同样地,自减操作也如此。在实际开发中,注意这个问题有助于规避一些算术错误。
3.5.2 关系运算符
关系运算符如表3.4所示。
表3.4 关系运算符

表3.4列出了所有关系运算符,下面是一些具体的示例:

输出结果:

要注意的是,如果两个对象均返回null,即使其类型不同,但其值相同,也是相等的。
3.5.3 类型判定运算符
类型判定运算符是在运行时判断两个对象类型是否一致的运算符,如表3.5所示。
表3.5 类型判定运算符

下面来看具体的示例:

输出结果:

我们知道,String类型是一个对象,属于Object的子类,因此String类也会具备Object类的一些方法。所以,可以将String类型转换为Object类型,然后使用Object类的方法。
3.5.4 赋值运算符
Dart编程语言中的赋值运算符如表3.6所示。
表3.6 赋值运算符

除了等号运算符直接将右侧的值赋给左侧,其他的运算符均相当于先执行运算,然后把运算后的值赋给左边的变量。看下面的代码示例:


运行结果:

详细的过程相当于“assignmentValue=assignmentValue+5”。
3.5.5 逻辑运算符
表3.7展示了Dart中的所有逻辑运算符。
表3.7 逻辑运算符

逻辑运算符的左右两侧通常都是布尔类型的表达式,经过逻辑运算符运算后依然得到布尔类型的结果。代码示例:

运行结果:

取反运算符的意义就是原布尔值的相反的结果,即原来是true的变为false,原来是false的变为true。
或运算符的意义就是对于两个或多个布尔表达式,只要其中一个为true,那么整体结果为true。因此,在IDE中,类似于示例中或运算符的写法可能会在false那里出现警告,因为第一个值已经是true,所以代码不会运行到false,这也是由编程语言中的懒特性决定的。
与运算符的意义是对于两个或多个布尔表达式,只有当表达式的值均为true时,整体的结果才为true;只要有一个表达式的结果为false,整体的计算结果就是false。因此,会得到上面的运行结果。
3.5.6 位操作运算符
Dart支持按位操作。在实际开发过程中,按位操作可能不及算术运算用处那么广泛,但在某些情况下,使用它可以使性能更高效、算法更巧妙。Dart的位操作运算符如表3.8所示。
表3.8 位操作运算符

其中,按位与、按位或和按位异或看上去和之前介绍过的逻辑运算符很像,要注意它们之间的区别。具体用法的示例如下:


输出结果:

位操作都是先将其转换为二进制数。比如按位与,bitValue的十六进制数是0x22,转换为二进制数后是100010;bitValueMask的十六进制数是0x0f,转换为二进制数后是001111。然后将这两个二进制数的每一位进行与操作,将得到000010的结果,这个结果仍然是二进制数,转换为十六进制数为0x02。因此,上面代码中的判断运算符将得到true的输出结果。你可以对其他的运算符如法炮制,先转换为二进制数,再运算,最后将二进制数转换为十六进制数,即最后的结果。
3.5.7 条件表达式
Dart编程语言支持两种条件表达式,其中一种格式如下:

如果条件判断为true,则执行表达式1,并返回结果;反之则执行表达式2,并返回结果。
另一种格式如下:

如果表达式1的值不是null,则返回表达式1的结果;反之则返回表达式2的结果。
示例如下:

运行结果:

上述示例很好地诠释了两种条件表达式的用法和区别。在某些条件和返回足够简单的情况下,建议使用条件表达式来替代if-else语句。
3.5.8 级联运算符
从严格意义上说,级联运算符实际上是Dart编程语言的一个特殊语法,并不是一个运算符。它的写法是两个点(..),用于在同一对象上的连续调用。考虑这样一个情况,现在有一个自定义坐标点的对象,其中包含x,y,z坐标值,给它赋值,并调用类自身的toString()方法输出这个对象的值。如果不采用级联运算符的话,代码如下:

毫无疑问,在代码中对x,y,z分别进行设置,然后输出结果,不存在任何问题。但是如果运用级联运算符的话,代码就可以更简洁,如下:

这样一行就搞定了,而且还避免了创建pointExp这个临时变量。
3.5.9 其他运算符
在Dart中,还有一些其他运算符,见表3.9。
表3.9 其他运算符

本书对这些运算符不再详细说明,请自行编写测试代码实践。