![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=1738786651-C3zLWrPMosi2rtKTCTxZhWQitW2oe3jp-0-b536bf0fa0652d770c21b14e7ce6ea2b)
所有带有运算符的都是表达式。在上述表格中,运算符的优先级顺序为从左到右,从上到下。对比下面两个表达式:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_91.jpg?sign=1738786651-B5rYNf6QKEGmh6vRGr6pO6EXO1m3Hl4b-0-635e708a74f5b28556cd7c026099d45f)
由于“%”的优先级高于“==”,且“==”的优先级高于“||”,因此上述代码运行后的结果如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_92.jpg?sign=1738786651-1L49paypnRbdicythtuWzYc7SbXs8RmS-0-288952e971f1b08145f3149471085958)
要注意的是,对于有两个操作数的运算符,其功能取决于左侧的操作数。
3.5.1 算术运算符
算术运算符很好理解,和传统的数学意义最为类似。所有算术运算符如表3.3所示。
表3.3 算术运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_93.jpg?sign=1738786651-fwlyjiSAxJuamAQT5iU3bFJh4G7LqIeF-0-3818d313c0c6f0b45c9bc7ec06c3cae1)
如表3.3所示,加法、减法、乘法、除法、取反都很好理解。但在Dart中直接做除法时,如果不能整除,就不会只返回整数,而是自动转换为小数返回。如果要只取整数部分,就需要使用“~/”。具体的算术运算符示例如下所示:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_94.jpg?sign=1738786651-ohe7jUG1COomCittnUz165SW7xzlOMsM-0-b95797c08f21957cc96f2a76e4324556)
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_95.jpg?sign=1738786651-xAdpHQGxYwuMFESEjMfgT9yp3fbB0tXc-0-4dcd5de0d549a4df5f2dd11723e902f8)
运行结果如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_96.jpg?sign=1738786651-IBdBWg50cgwkt3Kcvj2Fomhh9Vkwa8S5-0-01f159252146b91933eaeec6ace8a8c1)
和其他高级语言一样,Dart也支持变量自增/自减操作。经过自增操作,值比原来大1;经过自减操作,值比原来小1。我们会发现,自增和自减分别有两种不同的写法,那么它们的区别是什么呢?用下面的代码进行测试:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_97.jpg?sign=1738786651-K43sSz8HyQks1jsRMW2T6zLWq7dB7Qat-0-dc1488bb97f5dab40d34bade71fb2c0d)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_98.jpg?sign=1738786651-60zXdTgOLqElVM3GbIq7lVFqgvkTNNu5-0-85ae2da28e0d75cfe635c43d1c50e34c)
由此可见,++a立即见效,其表达式已经是自增之后的结果。而a++则不同,其表达式结果仍为原来的数值,在之后才会做加1的操作。同样地,自减操作也如此。在实际开发中,注意这个问题有助于规避一些算术错误。
3.5.2 关系运算符
关系运算符如表3.4所示。
表3.4 关系运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_99.jpg?sign=1738786651-C9Zs4wkYzYLP9ZTngHKQw9fa2MH3jy2Z-0-621f1a500f966cafa1e22d4b63d17757)
表3.4列出了所有关系运算符,下面是一些具体的示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_100.jpg?sign=1738786651-yZh772DE6AM0UtOjSTn0dbJdXPH1ZGXj-0-06289ef4c6e2cdfabace9423101f28f0)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_101.jpg?sign=1738786651-f7p6l2IAwe0AK7tWEVoE9MJpfnWk7Axq-0-a6e4155946a5a88804e64ec421da1a5e)
要注意的是,如果两个对象均返回null,即使其类型不同,但其值相同,也是相等的。
3.5.3 类型判定运算符
类型判定运算符是在运行时判断两个对象类型是否一致的运算符,如表3.5所示。
表3.5 类型判定运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_102.jpg?sign=1738786651-XUzOrTYVLzeIP0WL5mHSkb4KuLcGsDXK-0-fd16157eb2dadb8fee0ca422ed14a663)
下面来看具体的示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_103.jpg?sign=1738786651-vS9QdwXGjnPBY384TFQnokxA2b0cJ7ws-0-84584d06b501ff7a2b090dbe7d0f5859)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_104.jpg?sign=1738786651-Towkk6FbZlBXpcEWOXhUEEcrBluqZQed-0-e0af9979e25811b6f35aa7eeacea858c)
我们知道,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=1738786651-EKTSYSjLQsIHbN3Q5C6wgvUvwGOSUJxa-0-55c246a95d1e28cda68a478884481e63)
除了等号运算符直接将右侧的值赋给左侧,其他的运算符均相当于先执行运算,然后把运算后的值赋给左边的变量。看下面的代码示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_106.jpg?sign=1738786651-WncPaQcEy2wxr3av9CKb4o193ZX386CN-0-e3c41000b78c2939bd8705fb421a8f36)
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_107.jpg?sign=1738786651-yyAyTsXNlY2APUDSSvgLuZ3amiqmBXUa-0-88bb95f06acd4f8e9221ef12b4216507)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_108.jpg?sign=1738786651-lhOt9aGsJWAEcpM5BVLEvqiFyFC4b9ja-0-5947786b16c46aaf641411cf54e6ad7e)
详细的过程相当于“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=1738786651-uawth9PeXAkfc009g3DLSKEPL07De2ZK-0-44cd0ad49e857ac205bf96a2a9447de2)
逻辑运算符的左右两侧通常都是布尔类型的表达式,经过逻辑运算符运算后依然得到布尔类型的结果。代码示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_110.jpg?sign=1738786651-yAuFlGTkxGkvO0xg48lVtnXWRIplJPSu-0-9ec2a8543395f5c6111b544be819ba0d)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_111.jpg?sign=1738786651-vfq74Qn5XHK7m5buz6W9X7jH2gVyl6iN-0-3447e7bd72325cd87d7352070832be63)
取反运算符的意义就是原布尔值的相反的结果,即原来是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=1738786651-24w6MbqLfEJRYJRP9QYaN5htXkHzQsQk-0-f8e54713a38f9c717ab0856eab6225d8)
其中,按位与、按位或和按位异或看上去和之前介绍过的逻辑运算符很像,要注意它们之间的区别。具体用法的示例如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_113.jpg?sign=1738786651-3RRPeyQB4yGWUAxnlIlx8CsrnZaBqCNb-0-a13689ed26e0d94e871c5252d22ee4d7)
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_114.jpg?sign=1738786651-tgngk2ctQI9CwyDWzN2Mnr1wBDe6iNrx-0-5f27ef8d929a6602dcc23c0b1cf24e35)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_115.jpg?sign=1738786651-iLFaH8FWCkIrE5nG5WO9ZaQY84faJEr1-0-4185cc58424659c2a9698225671e74ba)
位操作都是先将其转换为二进制数。比如按位与,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=1738786651-D5X8pK6piOrxiQhVwAF4Zd88SUWdmVyd-0-1e4068ff0418fa837fa0a1e6d3d44755)
如果条件判断为true,则执行表达式1,并返回结果;反之则执行表达式2,并返回结果。
另一种格式如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_117.jpg?sign=1738786651-3DtHKEUqHeyjfDUCShnf3A89KGQeLOUg-0-bfa514891bdc31351cce0b197a5acf51)
如果表达式1的值不是null,则返回表达式1的结果;反之则返回表达式2的结果。
示例如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_118.jpg?sign=1738786651-0CgvBYyvsLnP0JcOupfvkQ9Yl6SkDpzg-0-e03fbb853f587a32ba2e965df6c9d34d)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_119.jpg?sign=1738786651-cyBFp2SD5Jp8tI8ha8kpVCR5B38YHOCK-0-960633ebe63ba021c6f1d947141562ca)
上述示例很好地诠释了两种条件表达式的用法和区别。在某些条件和返回足够简单的情况下,建议使用条件表达式来替代if-else语句。
3.5.8 级联运算符
从严格意义上说,级联运算符实际上是Dart编程语言的一个特殊语法,并不是一个运算符。它的写法是两个点(..),用于在同一对象上的连续调用。考虑这样一个情况,现在有一个自定义坐标点的对象,其中包含x,y,z坐标值,给它赋值,并调用类自身的toString()方法输出这个对象的值。如果不采用级联运算符的话,代码如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_120.jpg?sign=1738786651-2AiMv9vwEBfb1eugIfE71lduckkhZSmK-0-1106b11a48a9104d1c10db2ebcd059f9)
毫无疑问,在代码中对x,y,z分别进行设置,然后输出结果,不存在任何问题。但是如果运用级联运算符的话,代码就可以更简洁,如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_121.jpg?sign=1738786651-21wLvAJxIOWqcvBFj3fZhlKKwx1Ezhib-0-8a447323eb8572db6362a0e44c727140)
这样一行就搞定了,而且还避免了创建pointExp这个临时变量。
3.5.9 其他运算符
在Dart中,还有一些其他运算符,见表3.9。
表3.9 其他运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_122.jpg?sign=1738786651-tb42DbtXOmjWtA3aSiUPBAgyXJ9sdXL7-0-e8c5cdf92c9144682e28d0dc0677afbe)
本书对这些运算符不再详细说明,请自行编写测试代码实践。