![Flutter从0基础到App上线](https://wfqqreader-1252317822.image.myqcloud.com/cover/259/33831259/b_33831259.jpg)
3.5 运算符
运算符,也称为操作符。Dart编程语言定义了很多运算符,如表3.2所示。
表3.2 Dart的运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_90.jpg?sign=1739347578-p4jeWlHdiwAFOuB6axGWRmb4mWPA7FyO-0-cc3b0edfc5503090fa7f4300a0feda6d)
所有带有运算符的都是表达式。在上述表格中,运算符的优先级顺序为从左到右,从上到下。对比下面两个表达式:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_91.jpg?sign=1739347578-0WqhTknrmLtiEKT9IgbQv66pQEsyfpAt-0-a0ccb89054acc21fcc181f02da523398)
由于“%”的优先级高于“==”,且“==”的优先级高于“||”,因此上述代码运行后的结果如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_92.jpg?sign=1739347578-MLyCn1EbcoYhy6uY7z3VhmQDijyAWoiY-0-3392b5bc0eeea1940e9cad783b7c1e65)
要注意的是,对于有两个操作数的运算符,其功能取决于左侧的操作数。
3.5.1 算术运算符
算术运算符很好理解,和传统的数学意义最为类似。所有算术运算符如表3.3所示。
表3.3 算术运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_93.jpg?sign=1739347578-yGun4iFQvHHig9TGWuU4rTJTsalKri0v-0-74a289a219c2e4356a57443dbf3bec4d)
如表3.3所示,加法、减法、乘法、除法、取反都很好理解。但在Dart中直接做除法时,如果不能整除,就不会只返回整数,而是自动转换为小数返回。如果要只取整数部分,就需要使用“~/”。具体的算术运算符示例如下所示:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_94.jpg?sign=1739347578-l9aUPaAkigBXN2GGAjVSUuDCpRV1KQBy-0-c6db79bc9dde4d405aebbceed82719ab)
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_95.jpg?sign=1739347578-V4btxpwlk8qhXmr5God3NbKKGmjCXoEQ-0-3bf67139e9af2e992697aee4da2336f2)
运行结果如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_96.jpg?sign=1739347578-DZOpyChfNJhJdghYAZZ0Io8aeeGafn6q-0-72440cfcd40e62d26ad780a9ec432ada)
和其他高级语言一样,Dart也支持变量自增/自减操作。经过自增操作,值比原来大1;经过自减操作,值比原来小1。我们会发现,自增和自减分别有两种不同的写法,那么它们的区别是什么呢?用下面的代码进行测试:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_97.jpg?sign=1739347578-7y02VfEMRDG0nUI6yJ1PBfrj5ym0bp3X-0-3b4ea87840b95ca636afead5a85975f5)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_98.jpg?sign=1739347578-m4utqqDbVylpEj1YZnAeVOhprn59hrhX-0-96ab9fbb749df4c86ad5eda744adf76d)
由此可见,++a立即见效,其表达式已经是自增之后的结果。而a++则不同,其表达式结果仍为原来的数值,在之后才会做加1的操作。同样地,自减操作也如此。在实际开发中,注意这个问题有助于规避一些算术错误。
3.5.2 关系运算符
关系运算符如表3.4所示。
表3.4 关系运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_99.jpg?sign=1739347578-tiqZslZvHFg4YXhMi75q2aJW9Aw9G7VL-0-2e992758cae3feb156aad889987212d8)
表3.4列出了所有关系运算符,下面是一些具体的示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_100.jpg?sign=1739347578-yBRN6UuPvyYIBLXuvfoFFH1AZRXGpcYE-0-6bb447ed6e9af39c2231f8a4e1dfe96a)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_101.jpg?sign=1739347578-xcHTu8twEL41tIEdeLcF0RqucWG2vgNG-0-e9b9bdd80a6cacccc3d1c0d6b13aa58d)
要注意的是,如果两个对象均返回null,即使其类型不同,但其值相同,也是相等的。
3.5.3 类型判定运算符
类型判定运算符是在运行时判断两个对象类型是否一致的运算符,如表3.5所示。
表3.5 类型判定运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_102.jpg?sign=1739347578-JjjWs5DRmZURR9mOuGNkoVyZl10fsiku-0-2e44f84a431adc83457a7201a466842e)
下面来看具体的示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_103.jpg?sign=1739347578-XSLgyZWxfOBrvXX7pr6aArcbrx3NWLNJ-0-44ce9f50fab605a98dd40685887b034a)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_104.jpg?sign=1739347578-Lq2e1f70j3UIIruRa1AIVWejp7uc1V8D-0-c9618d3c40aaff3896b1c9e5cbed05d6)
我们知道,String类型是一个对象,属于Object的子类,因此String类也会具备Object类的一些方法。所以,可以将String类型转换为Object类型,然后使用Object类的方法。
3.5.4 赋值运算符
Dart编程语言中的赋值运算符如表3.6所示。
表3.6 赋值运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_105.jpg?sign=1739347578-FAZpZxNucOwjiSAu8ZAlT3Sn3MmWDagV-0-e1d79edbd6790230e0c88168a48edd40)
除了等号运算符直接将右侧的值赋给左侧,其他的运算符均相当于先执行运算,然后把运算后的值赋给左边的变量。看下面的代码示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_106.jpg?sign=1739347578-9O01XUvbqjlewmQOVcgDa4LhEcysRgHg-0-30ca8a2956badd2ad8ef7ab156dd1f9c)
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_107.jpg?sign=1739347578-lycwRTHRaUYA5izpHd5TkJZOoqFmzp1B-0-8ff6177c33c54f1cb2956859834f760e)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_108.jpg?sign=1739347578-mtt21sjCBMAHP0NqvAkZZz1eNTrqbxHo-0-c806a9bf846a488af3d2bd31221315d4)
详细的过程相当于“assignmentValue=assignmentValue+5”。
3.5.5 逻辑运算符
表3.7展示了Dart中的所有逻辑运算符。
表3.7 逻辑运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_109.jpg?sign=1739347578-5zgCBgUGF3EwcetOOomqCdPYnxwbbF3G-0-592900f87fd64386879881a6d8a63d85)
逻辑运算符的左右两侧通常都是布尔类型的表达式,经过逻辑运算符运算后依然得到布尔类型的结果。代码示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_110.jpg?sign=1739347578-MQAfjoWJpx5hRE58lKCMVcU2vhgGAtoJ-0-7dfe0d25db6c4a30bdf854db266d3dcb)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_111.jpg?sign=1739347578-VMjSW3eOSBXKdGedMDN7qRROIzBimigI-0-a8c9b7af40148b268482b2564f897596)
取反运算符的意义就是原布尔值的相反的结果,即原来是true的变为false,原来是false的变为true。
或运算符的意义就是对于两个或多个布尔表达式,只要其中一个为true,那么整体结果为true。因此,在IDE中,类似于示例中或运算符的写法可能会在false那里出现警告,因为第一个值已经是true,所以代码不会运行到false,这也是由编程语言中的懒特性决定的。
与运算符的意义是对于两个或多个布尔表达式,只有当表达式的值均为true时,整体的结果才为true;只要有一个表达式的结果为false,整体的计算结果就是false。因此,会得到上面的运行结果。
3.5.6 位操作运算符
Dart支持按位操作。在实际开发过程中,按位操作可能不及算术运算用处那么广泛,但在某些情况下,使用它可以使性能更高效、算法更巧妙。Dart的位操作运算符如表3.8所示。
表3.8 位操作运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_112.jpg?sign=1739347578-sm18oCpsdk3agirUYrBOmx9SB6KBDVHX-0-dc09843236de5744b64b6b280a811724)
其中,按位与、按位或和按位异或看上去和之前介绍过的逻辑运算符很像,要注意它们之间的区别。具体用法的示例如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_113.jpg?sign=1739347578-WzRYtieEBq6g2BF9I46yBEd6CBzumOuj-0-ee881d711357d9bc7202cfac9c75b73f)
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_114.jpg?sign=1739347578-wUtKXMIaMb4jQ8JTIyxuY0g10a2H58VK-0-9b46307133eccf18db454dfbae2b4d82)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_115.jpg?sign=1739347578-GLmV570cAfffjmPkmmq3GmUKDb1fS8Dl-0-c644520aecf06d34580045299e1249e2)
位操作都是先将其转换为二进制数。比如按位与,bitValue的十六进制数是0x22,转换为二进制数后是100010;bitValueMask的十六进制数是0x0f,转换为二进制数后是001111。然后将这两个二进制数的每一位进行与操作,将得到000010的结果,这个结果仍然是二进制数,转换为十六进制数为0x02。因此,上面代码中的判断运算符将得到true的输出结果。你可以对其他的运算符如法炮制,先转换为二进制数,再运算,最后将二进制数转换为十六进制数,即最后的结果。
3.5.7 条件表达式
Dart编程语言支持两种条件表达式,其中一种格式如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_116.jpg?sign=1739347578-EWMvzCuru2RKTyhpxv8kJ8sXkpIc344w-0-ca8432dfe567c9876100f00c4e239f03)
如果条件判断为true,则执行表达式1,并返回结果;反之则执行表达式2,并返回结果。
另一种格式如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_117.jpg?sign=1739347578-N0UJrKNy7oUCB1fsI6sYS7oWS2gg00Su-0-91083d2a1e4aee46d4f7849178ba3ce9)
如果表达式1的值不是null,则返回表达式1的结果;反之则返回表达式2的结果。
示例如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_118.jpg?sign=1739347578-7rVh6D98TA4LFrxcpNQwb5ubu4YFGwBg-0-830ec9bd59d929ab7646ef397d7440f9)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_119.jpg?sign=1739347578-3AFmjo5ydQPwHZnz3hwKXAHLRZzPvdvE-0-3cf97f94efcd24f17b17b15a10e91096)
上述示例很好地诠释了两种条件表达式的用法和区别。在某些条件和返回足够简单的情况下,建议使用条件表达式来替代if-else语句。
3.5.8 级联运算符
从严格意义上说,级联运算符实际上是Dart编程语言的一个特殊语法,并不是一个运算符。它的写法是两个点(..),用于在同一对象上的连续调用。考虑这样一个情况,现在有一个自定义坐标点的对象,其中包含x,y,z坐标值,给它赋值,并调用类自身的toString()方法输出这个对象的值。如果不采用级联运算符的话,代码如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_120.jpg?sign=1739347578-KQ56PBhaiwxbDLMGmev6yVYrnopzdXeD-0-a061477af49bb16685f67254c52f34c5)
毫无疑问,在代码中对x,y,z分别进行设置,然后输出结果,不存在任何问题。但是如果运用级联运算符的话,代码就可以更简洁,如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_121.jpg?sign=1739347578-gsMlT9FMjq8H4WlocRQtwBCRYIH1TlgR-0-51784873259da90a27ae985621a14483)
这样一行就搞定了,而且还避免了创建pointExp这个临时变量。
3.5.9 其他运算符
在Dart中,还有一些其他运算符,见表3.9。
表3.9 其他运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_122.jpg?sign=1739347578-REfmNVUErZMkkODrwdUtHzniOFLZtKRi-0-09e7c115b5b6a46ddefb178bd8c922bb)
本书对这些运算符不再详细说明,请自行编写测试代码实践。