运算符的作用是操纵对象和数据,它以一个或多个变量为基础,生成新的值。
运算符具有优先级和结合性。优先级决定一个表达式存在多个运算符时各部分的计算顺序。结合性决定了在相同优先级的情况下是从左到右(左结合)还是从右到左(右结合)。Kotlin中运算符优先
级和结合性参见下表(数字越小,优先级越高):
符号 | 优先级 | 结合性 | 目数 | 说明 |
---|---|---|---|---|
. | 1 | 从左到右 | 双目 | 点 |
() | 1 | 从左到右 | 双目 | 小括号 |
[] | 1 | 从左到右 | 双目 | 中括号 |
++ | 2 | 从右到左 | 单目 | 前缀增 |
-- | 2 | 从右到左 | 单目 | 前缀减 |
+ | 2 | 从右到左 | 单目 | 正号 |
- | 2 | 从右到左 | 单目 | 负号 |
++ | 2 | 从右到左 | 单目 | 后缀增 |
-- | 2 | 从右到左 | 单目 | 后缀减 |
! | 2 | 从右到左 | 单目 | 逻辑非 |
* | 3 | 从左到右 | 双目 | 乘法 |
/ | 3 | 从左到右 | 双目 | 除法 |
% | 3 | 从左到右 | 双目 | 取余 |
+ | 4 | 从左到右 | 双目 | 加法 |
- | 4 | 从左到右 | 双目 | 减法 |
< | 5 | 从左到右 | 双目 | 小于 |
<= | 5 | 从左到右 | 双目 | 小于等于 |
> | 5 | 从左到右 | 双目 | 大于 |
>= | 5 | 从左到右 | 双目 | 大于等于 |
== | 6 | 从左到右 | 双目 | 等于 |
!= | 6 | 从左到右 | 双目 | 不等于 |
&& | 7 | 从左到右 | 双目 | 逻辑与 |
|| | 8 | 从左到右 | 双目 | 逻辑或 |
= | 9 | 从左到右 | 双目 | 赋值 |
+= | 9 | 从左到右 | 双目 | 复合赋值运算符加 |
-= | 9 | 从左到右 | 双目 | 复合赋值运算符减 |
*= | 9 | 从左到右 | 双目 | 复合赋值运算符乘 |
/= | 9 | 从左到右 | 双目 | 复合赋值运算符除 |
%= | 9 | 从左到右 | 双目 | 复合赋值运算符取余 |
熟悉Java的同学从上表中并没有看到 |
、&
、^
、~
和移位相关的操作符。在Kotlin中通过 and
、or
、xor
和 inv()
实现位操作;通过 shr
、shl
、ushr
实现移位操作,并且没有移位赋值操作符。
实际操作中为了方便阅读,明确执行顺序,一般通过添加括号而不是依赖运算符的优先级来控制计算顺序。
1.赋值运算符 =
=
将符号右边的值复制到左边。右边的值可以是变量、常量 和任何表达式。比如:
val a = 5
var b = 3 + 45
2.算术运算符 +
、-
、*
、/
、%
基本算术运算符都是一样的这里就不再多说,下面举几个代码实例:
val num1 = 3
val num2 = 4
val i = num1 + num2 // i = 3 + 4 = 7
val j = num1 - num2 // j = 3 - 4 = -1
val k = num1 * num2 // k = 3 * 4 = 12
val m = num1 / num2 // m = 3 / 4 = 0
val n = num1 % num2 // n = 3 % 4 = 3
一元运算符 +
和 -
。 +
保持变量原值。 -
修改变量值为原值的相反数。
val a = -46
val b = +a // b= -46
val c = -a // c = 46
3.关系运算符>
、>=
、<
、<=
、!=
、==
其中 >
、>=
、<
、<=
适用于所有实现了 Comparable 接口的对象,!=
、==
适用于任何对象。下面给出一些示例代码:
var i = 23
var j = 12
println(i < j) // 输出结果为 false
println(i >= j) // 输出结果为 true
val a = Integer(5)
val b = Integer(5)
println(a == b) // 输出结果为 true
println(a != b) // 输出结果为 false
4.逻辑运算符||
、&&
、!
逻辑运算符只适用于 Boolean 或者 boolean类型, 经过它运算后生成一个布尔值。比如:
val b = false
println(!b) // 输出true
var k = 23
val c = b || k>2 && k ==23
println(c) // 输出true
5.位运算符
Kotlin中使用 or
、and
、xor
操作符和方法inv() 分别表示按位 或 、 与、异或 、求反操作。示例代码:
var i = 0b0011 // 十进制数3
var j = 0b1010 // 十进制数10
println(i or j) // 11
println(i and j) // 2
println(i xor j) // 9
println(i.inv()) // -4
补充:
机器数:
数字在计算机中二进制表示的方式,叫做这个数的机器数。高位用于存放数字的符号,0表示正数,1表示负数.
真值:
带符号位的机器数对应的真正数值称为机器数的真值。比如,有符号数 10000001 的真值为 -1, 而不是2^7 +1 = 129。00000001 的真值为 1.
原码:
原码定义为符号位加上真值的绝对值。比如,+2 的原码为 00000010,; -2 的原码为 10000010 。
反码:
反码定义: 1. 如果是正数,那么其反码就是原码本身; 2.如果是负数,那么原码符号位不变,其余各位取反。 比如 +2 原码为 00000010 , 反码为 00000010; -2 原码为 10000010 , 反码为 11111101。
补码:
补码定义:1. 如果是正数,那么其补码就是原码本身; 2.如果是负数,那么原码符号位不变,其余各位取反,最后 +1 。 比如 +2 原码为 00000010 , 反码为 00000010; -2 原码为 10000010 , 补码为 11111110。由于计算机中存储的是数值的补码,针对示例代码中变量:
i = 0b0011 , 其完整的二进制(int类型用 32 位 2 进制表示)表示为:
0000 0000 0000 0000 0000 0000 0000 0011
j = 0b1010 , 其完整的二进制表示为:
0000 0000 0000 0000 0000 0000 0000 1010
or (按位或)操作:
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 1010
0000 0000 0000 0000 0000 0000 0000 1011 => 2^3 + 2^1 + 1 = 11
and (按位与)操作:
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 1010
0000 0000 0000 0000 0000 0000 0000 0010 => 2^1 = 2
xor (按位异或)操作:
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 1010
0000 0000 0000 0000 0000 0000 0000 1001 => 2^3 + 1 = 9
inv()(按位求反)操作:
0000 0000 0000 0000 0000 0000 0000 0011
1111 1111 1111 1111 1111 1111 1111 1100 => - 2^2 = -4
6.移位运算符
Kotlin中使用 shr
、shl
、ushr
操作符实现移位操作,并且没有移位赋值符合运算符。可用下面的方案来测试了解各个操作符的作用:
var i = 0b0111 // 十进制数7
println(i shr 2)
println(i shl 2) // 左移,相当于 2^n * i , n 移位位数 , i操作数
println(i ushr 2)
var j = -0b111 // 十进制数 -7
println(j shr 2) // 有符号右移,最左边用符号位填充
println(j shl 2)
println(j ushr 2) // 无符号右移,最左边位用0填充,负数变正数
补充:相同的,针对移位操作示例代码中的变量:
i = 0b0111 , 其完整的二进制表示为:
0000 0000 0000 0000 0000 0000 0000 0111
shr 2 , 有符号右移两位, 最左边用符号位填充 , 结果为:
0000 0000 0000 0000 0000 0000 0000 0001 => 1
shl 2, 左移两位, 最右边用 0 填充 , 结果为:
0000 0000 0000 0000 0000 0000 0001 1100 => 2^4 + 2^3 + 2^2 = 28
ushr 2, 无符号右移两位, 最左边用 0 填充 , 结果为:
0000 0000 0000 0000 0000 0000 0000 0001 => 1
j = -0b0111 , 其完整的二进制表示为:
1111 1111 1111 1111 1111 1111 1111 1001
shr 2 , 有符号右移两位, 最左边用符号位填充 , 结果为:
1111 1111 1111 1111 1111 1111 1111 1110 => -2
shl 2, 左移两位, 最右边用 0 填充 , 结果为:
1111 1111 1111 1111 1111 1111 1110 0100 => - 28
ushr 2, 无符号右移两位, 最左边用 0 填充 , 结果为:
0011 1111 1111 1111 1111 1111 1111 1110 => 1073741822
示例代码中几乎包含了所有的运算符,特别需要注意关系运算符和逻辑运算符中的示例代码。