03. Kotlin 运算符
算术运算符
Kotlin 中的算术运算符主要用来组织数值类型数据的算术运算,按照参加运算的操作数的不同可以分为一元运算符和二元运算符。
一元算术运算符
算术一元运算符一共有 3 个,分别是-、++和–。
运算符 | 名称 | 说明 | 例子 |
---|---|---|---|
- | 取反符号 | 取反运算 | b = -a |
++ | 自加一 | 先取值再加一,或先加一再取值 | a或a |
– | 自减一 | 先取值再减一,或先减一再取值 | a–或–a |
二元算术运算符
二元运算符包括:+、-、*、/和%,这些运算符对数值类型数据都有效。
运算符 | 名称 | 说明 | 例子 |
---|---|---|---|
+ | 加 | 求 a 加 b 的和,还可用于 String 类型,进行字符串连接操作 | a + b |
- | 减 | 求 a 减 b 的差 | a - b |
* | 乘 | 求 a 乘以 b 的积 | a * b |
/ | 除 | 求 a 除以 b 的商 | a / b |
% | 取余 | 求 a 除以 b 的余数 | a % b |
位运算符
位运算是以二进位(bit)为单位进行运算的,操作数和结果都是整型数据。位运算符有如下几个运算符:位反、位与、位或、位异或、有符号右移、左移和无符号右移等,具体说明参见表。
表 位运算符
运算符 | 名称 | 例子 | 说明 |
---|---|---|---|
inv | 位反 | x.inv() | 将 x 的值按位取反 |
and | 位与 | x and y 或 x.and(y) | x 与 y 位进行位与运算 |
or | 位或 | x or y 或 x.or(y) | x 与 y 位进行位或运算 |
xor | 位异或 | x xor y 或 x.xor(y) | x 与 y 位进行位异或运算 |
shr | 有符号右移 | x shr y 或 x.shr(y) | x 右移 y 位,高位采用符号位补位 |
shl | 左移 | x shl y 或 x.shl(y) | x 左移 y 位,低位用 0 补位 |
ushr | 无符号右移 | x ushr a 或 x.ushr(y) | x 右移 y 位,高位用 0 补位 |
如表所示可见 Kotlin 的位运算不是采用如 +
、-
、*
、/
等特殊符号,而是使用了函数。而且除了位反 inv 和无符号右移 ushr 函数外,其他的位运算函数还可以用中缀运算符表示,中缀运算符本质上是一个函数,该函数只有一个参数。中缀运算符模拟+、-、*、/等符号运算符,函数名在中间,省略小括号。例如:
1 | x.and(y) // 函数表示 |
注意 无符号右移运算符仅被允许用在 Int 和 Long 整数类型,如果用于 Short 或 Byte 数据,则数据在位移之前,转换为Int 类型后再进行位移计算。
关系(比较)运算符
关系运算是比较两个表达式大小关系的运算,它的结果是布尔类型数据,即 true 或 false。关系运算符有 8 种,具体说明参见表。
运算符 | 名称 | 说明 | 例子 |
---|---|---|---|
== |
等于 | a 等于 b 时返回 true,否则返回 false。可以应用于基本数据类型和引用类型,引用类型比较两个对象内容是否相等。==会调用 equals 函数实现比较 | a == b |
!= |
不等于 | 与 == 相反 | a!=b |
> |
大于 | a 大于b时返回true,否则返回 false | a>b |
< |
小于 | a 小于b时返回true,否则返回 false | a<b |
>= |
大于等于 | a 大于等于 b 时返回 true,否则返回 false | a >= b |
<= |
小于等于 | a 小于等于 b 时返回 true,否则返回 false | a <=b |
=== |
引用等于 | 用于引用类型比较,比较两个引用是否是同一个对象 | a === b |
!== |
引用不等于 | 与 === 相反 | a !== b |
相等性检查
Kotlin 的 == 运算符和 equals 函数等同于 Java 的 equals 函数,用于结构比较。
Kotlin 中的 ===
运算符等同于 Java 的 == 运算符,用于比较引用。
1 | val authors = setOf("Shakespeare", "Hemingway", "Twain") |
逻辑运算符
如果想清晰地表达复杂逻辑,需要用到逻辑运算符。
逻辑运算符是对布尔型变量进行运算,其结果也是布尔型。
运算符 | 名称 | 说明 | 例子 |
---|---|---|---|
! |
逻辑非 | a 为 true 时,值为 false,a 为 false 时,值为 true | !a |
&& |
逻辑与 | ab 全为 true 时,计算结果为true,否则为 false。&& 与 & 区别:如果 a 为 false,则不计算 b(因为不论 b 为何值,结果都为false) | a && b |
|| |
逻辑或 | ab 全为 false 时,计算结果为 false,否则为 true。| 与 || 区别:如果 a 为 true,则不计算 b(因为不论 b 为何值,结果都为true) |
`a |
&& 和 || 都具有短路计算的特点:例如 x && y,如果 x 为 false,则不计算 y(因为不论 y 为何值,“与”操作的结果都为false);而对于x || y,如果 x 为 true,则不计算 y(因为不论 y 为何值,“或”操作的结果都为true)。
这种短路形式的设计,使它们在计算过程中就像电路短路一样采用最优化的计算方式,从而提高效率。
除了条件语句,逻辑运算符还能用于许多其他表达式,包括变量定义。
1 | val auraVisible = isBlessed && healthPoints > 50 || isImmortal |
其他运算符
除了前面介绍的主要运算符,kotlin 还有一些其他运算符。
- 冒号(:)。用于变量或常量类型声明,以及声明继承父类和实现接口。
- 小括号。起到改变表达式运算顺序的作用,它的优先级最高。
- 中括号([])。索引访问运算符号。
- 引用号(.)。调用函数或属性运算符。
- 赋值号(=)。赋值是用等号运算符(=)进行的。
- 可空符(?)。标识一个可空类型。
- 安全调用运算符(?.)。调用非空类型的函数或属性。
- Elvis运算符(?:)。空值合并运算符。
- 非空断言(!!)。断言可空表达式为非空。
- 双冒号(::)。引用类、属性或函数。
- 区间(…)。表示一个范围区间。
- 箭头(->)。用来声明 Lambda 表达式。
- 展开运算符(*)。将数组传递给可变参数时使用。
除上述运算符位,还有一些鲜为人知的运算符,随着学习的深入用到后再为大家介绍,这里就不再赘述了。
区间运算符
1 | fun main(args: Array<String>) { |
为了处理可空数据类型,这里详细介绍如下运算符:
- 安全调用运算符:?.
- Elvis 运算符:?:
- 非空断言:!!
- 安全转换运算符:as?
安全调用运算符(?.)
1 | val divNumber1 = divide(100, 0) |
1 | >>> Output: |
上述代码自定义了 divide 函数进行除法运算,当参数 n2 为 0 的情况下,函数返回空值,所以函数返回类型必须是 Double 的可空类型,即 Double?。
非空断言运算符(!!)
可空类型变量可以使用非空断言运算符(!!)调用非空类型的函数或属性。非空断言运算符(!!)顾名思义就是断言可空类型变量不会为空,调用过程是存在风险的,如果可空类型变量真的为空,则会抛出空指针异常;如果非则可以正常调用函数或属性。
修改代码如下: val result1 = divNumber1!!.plus(100) // divNumber1+100,结果110.0
Elvis 运算符(?:)
有的时候在可空类型表达式中,当表达式为空值时,并不希望返回默认的空值,而是其他数值。此时可以使用 Elvis运算符(?:),也称为空值合并运算符,Elvis 运算符有两个操作数,假设有表达式:A ?: B,如果A不为空值则结果为A;否则结果为B。
Elvis 运算符经常与安全调用运算符结合使用,重写上一节示例代码如下:
val result1 = divNumber1?.plus(100) ?: 0 // divNumber1+100,结果0
Elvis 运算符由来 Elvis 一词是指美国摇滚歌手埃尔维斯·普雷斯利(Elvis Presley),绰号“猫王”。由于他的头型和眼睛很有特点,不用过多解释,从图可见为什么
?:
叫做 Elvis 了。
in 和 !in
判断一个数值是否在区间中可以使用 in 关键字。而 !in 关键字,则是判断一个值不在区间中。此外,这两个关键字(in 和 !in)还可以判断一个数值是否集合或数组中。
运算符优先级
在一个表达式计算过程中,运算符的优先级非常重要。
如下表所示,运算符的优先级从高到低,同一行具有相同的优先级。二元运算符计算顺序从左向右,但是优先级 15 的赋值运算符的计算顺序从右向左的。
表 运算符优先级
优先级 | 运算符 |
---|---|
1 | 小括号 |
2 | 后缀运算符 ++、–、.、?.、? |
3 | 前缀运算符-、+、++、–、! |
4 | :、as、as? |
5 | *、/、% |
6 | +、- |
7 | 区间… |
8 | 中缀运算符 |
9 | Elvis运算符 ?: |
10 | in、!in、is、!is |
11 | <、>、<=、>= |
12 | 、!=、=、!== |
13 | && |
14 | | |
15 | =、+=、-=、*=、/=、%= |
运算符优先级顺序,从高到低是:算术运算符 → 位运算符 → 关系运算符 → 逻辑运算符 → 赋值运算符。
参考
Kotlin 从小白到大牛
https://www.ituring.com.cn/book/tupubarticle/19723?bookID=2621&type=tubook&subject=第 8 章 运算符