![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=1739204715-dSuQGnWJOz4NyCZbLk1MAVduQxOJZxww-0-47c6086986bda6c676ab361b7f5c5139)
所有带有运算符的都是表达式。在上述表格中,运算符的优先级顺序为从左到右,从上到下。对比下面两个表达式:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_91.jpg?sign=1739204715-JcM3JRtivlGNX0bMi1HKkikQZPZ5QCIm-0-6ebd2537e3fc88d8d65b945e33d6c35c)
由于“%”的优先级高于“==”,且“==”的优先级高于“||”,因此上述代码运行后的结果如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_92.jpg?sign=1739204715-xuWuoktmgLXyurWbqDCLfix35EYMRAj7-0-675fbc4937798840458858b32a15fc5a)
要注意的是,对于有两个操作数的运算符,其功能取决于左侧的操作数。
3.5.1 算术运算符
算术运算符很好理解,和传统的数学意义最为类似。所有算术运算符如表3.3所示。
表3.3 算术运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_93.jpg?sign=1739204715-H2hoKIgM9GT6luOibI1fLwhEb24AnZ4S-0-1ce616aa04725a80113ee8bd196fa158)
如表3.3所示,加法、减法、乘法、除法、取反都很好理解。但在Dart中直接做除法时,如果不能整除,就不会只返回整数,而是自动转换为小数返回。如果要只取整数部分,就需要使用“~/”。具体的算术运算符示例如下所示:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_94.jpg?sign=1739204715-T85wgs2dyhdnA9eU68vbsskGhfUuGdMj-0-1b1b6697b77f71f235cee67460adb1b3)
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_95.jpg?sign=1739204715-frx86fQlrkUwk4KVRybasWIa7QWvVe86-0-56e1adb4e6cbe547ece4c7f7dbb6ad4b)
运行结果如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_96.jpg?sign=1739204715-VA0R28GCYLHm2n0cl8hTep3LX0HqCc4r-0-61b5653137a753fa0524c80d6ead71e0)
和其他高级语言一样,Dart也支持变量自增/自减操作。经过自增操作,值比原来大1;经过自减操作,值比原来小1。我们会发现,自增和自减分别有两种不同的写法,那么它们的区别是什么呢?用下面的代码进行测试:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_97.jpg?sign=1739204715-YugRRpkjf8T3Y54CUCprvu7ln4tpAGE0-0-66d9ea7ed0a1b7af74bc78059cabc5df)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_98.jpg?sign=1739204715-m0vZMrRuHH4OVZIo6XPXxdgxOHyEwgr0-0-803067b19fed381d1b3b885cfa6fd308)
由此可见,++a立即见效,其表达式已经是自增之后的结果。而a++则不同,其表达式结果仍为原来的数值,在之后才会做加1的操作。同样地,自减操作也如此。在实际开发中,注意这个问题有助于规避一些算术错误。
3.5.2 关系运算符
关系运算符如表3.4所示。
表3.4 关系运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_99.jpg?sign=1739204715-0uqHAyY7aOIHB8nZhcGs9OaJT4STi16c-0-90b8e827ed9b23ca12ccec731dc1ea1d)
表3.4列出了所有关系运算符,下面是一些具体的示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_100.jpg?sign=1739204715-5gTG1zcgJ6CirqvfLQNdYAXb9CfV5Jp4-0-2a85047b639bf0279aaa89282dcf1e07)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_101.jpg?sign=1739204715-sQjYbIrUHDbSa2KLShW7iCr1EzPrzpIk-0-a434b57d6b44c73042b4f606339a9b9c)
要注意的是,如果两个对象均返回null,即使其类型不同,但其值相同,也是相等的。
3.5.3 类型判定运算符
类型判定运算符是在运行时判断两个对象类型是否一致的运算符,如表3.5所示。
表3.5 类型判定运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_102.jpg?sign=1739204715-NFBL9s9shYBQEWq6j63zlXDYqwOkWwVX-0-6bdde12cd11ddc7d91e27738fef17fca)
下面来看具体的示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_103.jpg?sign=1739204715-TvAzvO6DfI5Vr6pIYKMy7ix56mAwkVvK-0-3dc173e2305c52f75b1438bd8eea6060)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_104.jpg?sign=1739204715-nWZFX97R9sIR5HRhhZNCq58nRsOtGkXu-0-00717b82873928ff1f6874571f254158)
我们知道,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=1739204715-4Jtq3NyJ21UozJAvFuHWM1iNGT2MxNxU-0-4fdfed5c4ae23b4592fff9f669be9e80)
除了等号运算符直接将右侧的值赋给左侧,其他的运算符均相当于先执行运算,然后把运算后的值赋给左边的变量。看下面的代码示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_106.jpg?sign=1739204715-nYyupxo9srVAwQaqRaxq9y61vbUPyrKZ-0-3b81ccd4fc2db54cb89c7940dc29bff4)
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_107.jpg?sign=1739204715-uY5rVvvKymu6PZa9ly4ImZKkJSzlkZik-0-6e5b244b14c65552f7c4654462d87d54)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_108.jpg?sign=1739204715-N8dMc9LIsgd7SX164ywcI9sXXuhoA5Y8-0-204c076e35067bae9bed99a87c45a591)
详细的过程相当于“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=1739204715-2VfgajwDpPeR6hFIdP3WEor5WhttOVmm-0-746ad9604308535ba0c60e26df74e561)
逻辑运算符的左右两侧通常都是布尔类型的表达式,经过逻辑运算符运算后依然得到布尔类型的结果。代码示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_110.jpg?sign=1739204715-EIstOpSxouheuJuGrgDAcmPIBrgIl34O-0-a2ba56797941ff41655052b3a9ff67b5)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_111.jpg?sign=1739204715-OOawKpMXeoDcqU8HxY6csxdZQyav5TIv-0-0e2cdc9a5afa3383879971bdf79e27bb)
取反运算符的意义就是原布尔值的相反的结果,即原来是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=1739204715-wo99YUhDups8LQisItg44DCwi75deeBC-0-31a4b284a15a323d894786ad19538f84)
其中,按位与、按位或和按位异或看上去和之前介绍过的逻辑运算符很像,要注意它们之间的区别。具体用法的示例如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_113.jpg?sign=1739204715-JwJpJwlrUfvRGxRzUvkeeRJKW3X2V3j6-0-2dab1ca8947d7189fb25b4abfaf1bfad)
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_114.jpg?sign=1739204715-MOfMoCd4usfO8GahySttTxXYVDzVhBJW-0-77d57d3b597f58fa60adf31c10909576)
输出结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_115.jpg?sign=1739204715-pPfM6SHF72b3EBxz2LwOyW5ddDAkKuJ5-0-ba60caf78737b650e1dc4ea0d8cddee6)
位操作都是先将其转换为二进制数。比如按位与,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=1739204715-KuZ0JgGFS364dpDqr9jBvalYVcE7XtUw-0-f4f43a803b1dd0fd0718620a386d3220)
如果条件判断为true,则执行表达式1,并返回结果;反之则执行表达式2,并返回结果。
另一种格式如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_117.jpg?sign=1739204715-HIj3POUsfhppEGmSIqQTO09eadcqlNyE-0-9a47f0641b7231082109d20a4743b948)
如果表达式1的值不是null,则返回表达式1的结果;反之则返回表达式2的结果。
示例如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_118.jpg?sign=1739204715-QeU5EIUVR8hnBrPUURMAbpmcn6kxAC5g-0-e0920d383e04a5f362a8c4bed51e1ec4)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_119.jpg?sign=1739204715-L7K9Mw0hzaOCXa675Z4KpRo8i1HUYAlT-0-5c49cc9df88ae3807fde0b76061033cf)
上述示例很好地诠释了两种条件表达式的用法和区别。在某些条件和返回足够简单的情况下,建议使用条件表达式来替代if-else语句。
3.5.8 级联运算符
从严格意义上说,级联运算符实际上是Dart编程语言的一个特殊语法,并不是一个运算符。它的写法是两个点(..),用于在同一对象上的连续调用。考虑这样一个情况,现在有一个自定义坐标点的对象,其中包含x,y,z坐标值,给它赋值,并调用类自身的toString()方法输出这个对象的值。如果不采用级联运算符的话,代码如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_120.jpg?sign=1739204715-GUrNwmVbjAthMIOkjIMlRVS2WuFo0Uaw-0-4058d592df37d56ca8c4e1cee39d163e)
毫无疑问,在代码中对x,y,z分别进行设置,然后输出结果,不存在任何问题。但是如果运用级联运算符的话,代码就可以更简洁,如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_121.jpg?sign=1739204715-xcgNH8wbuZBUHJLp8eS2ga96kWO4bY5G-0-53ad72295ee681c160c2d03668d5e73f)
这样一行就搞定了,而且还避免了创建pointExp这个临时变量。
3.5.9 其他运算符
在Dart中,还有一些其他运算符,见表3.9。
表3.9 其他运算符
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_122.jpg?sign=1739204715-OfAHXmxthtd9yb1FVpuHF4YCqs0uWqr7-0-48ce360b6c72b5919b040faca7b91c21)
本书对这些运算符不再详细说明,请自行编写测试代码实践。