1. 简介
是的,Kotlin 也支持位运算。尽管没有像 C 系语言那样使用常见的符号,比如 <<*, *>>, |, &, 和 ^,但 Kotlin 提供了基于 Int
和 Long
类型的函数来完成这些操作。
Kotlin 社区曾就是否支持位运算符进行了长达十年的讨论:KT-1440。支持者认为这是某些底层领域(如音频或视频处理)的刚需;反对者则认为可读性更重要,过多使用位运算会让代码难以理解。
目前,Kotlin 选择通过函数的方式来支持位运算。
2. Kotlin 位运算与 Java 的对比
大多数开发者都接触过位运算。下面对比 Kotlin 与 Java 的语法差异:
操作名称 | Java 运算符 | Kotlin Int/Long 方法 |
---|---|---|
按位与(AND) | a & b |
a and b |
按位或(OR) | a | b |
a or b |
异或(XOR) | a ^ b |
a xor b |
取反(Inversion) | ~a |
a.inv() |
左移(Shift Left) | a << b |
a shl b |
有符号右移(Signed Right Shift) | a >> b |
a shr b |
无符号右移(Unsigned Right Shift) | a >>> b |
a ushr b |
Java 还支持复合赋值操作符,如 |=
,但在 Kotlin 中需要手动写成 a = a or b
。
3. 位运算是如何工作的
了解了 Kotlin 的语法后,我们来看看这些操作到底对数据做了什么。
3.1. 按位与、按位或、取反
这些操作与逻辑运算类似,但作用于每个 bit 上:
val a = 0b10011 // 19
val b = 0b11110 // 30
assert(a and b == 0b10010) // 18
按位或:
val a = 0b101001 // 41
val b = 0b110011 // 51
assert(a or b == 0b111011) // 59
异或:
val a = 0b110101
val b = 0b101010
assert(a xor b == 31) // 11111
取反是最简单的,所有 0 变 1,1 变 0。但注意 Int
是 32 位,Long
是 64 位,所以对短于 32 位的二进制数取反后,需要使用 and
掩码处理高位:
assert(0b101100.inv() and 0b111111 == 0b010011)
3.2. 位移操作
位移操作就是将二进制数整体左移或右移指定位数:
assert(0b110011 shl 2 == 0b11001100)
✅ 左移只有一种,但右移有两种:有符号和无符号。
- **无符号右移 (
ushr
)**:左边补 0,结果始终为正。
assert(-0b1100110011 ushr 22 == 0b1111111111)
- **有符号右移 (
shr
)**:左边补原最高位,保留符号不变。
assert(0b1100110011 shr 2 == 0b11001100)
assert(0b11111111111111111111110011001101 shr 2 == 0b111111111111111111111100110011)
4. 位运算的应用场景
虽然位运算看起来简单,但在底层处理中非常高效,很多 CPU 指令只需一个周期即可完成。例如:
- 左移 = 乘以 2^n
- 右移 = 除以 2^n
assert(12 shr 2 == 3) // 12 / 4
assert(3 shl 3 == 24) // 3 * 8
相比普通的乘除法,位运算效率更高。
4.1. 位掩码(Bitmask)
位掩码常用于标志位管理。比如判断某个 flag 是否开启:
val SKY_IS_BLUE_MASK = 0b00000000000001000000000000
fun isSkyBlue(worldProperties: Int): Boolean =
worldProperties and SKY_IS_BLUE_MASK != 0
assert(isSkyBlue(0b10011100111101011101010101))
4.2. 合并多个标志位
使用 or
可以将多个标志合并:
val SKY_IS_BLUE = 0b00000000000001000000000000
val SUN_IS_SHINING = 0b00000000000000100000000000
val skyIsBlueAndSunShines = SKY_IS_BLUE or SUN_IS_SHINING // 0b00000000000001100000000000
这种方式节省内存,且操作高效,适合嵌入式系统、协议解析、权限控制等场景。
5. 总结
✅ Kotlin 支持完整的位运算功能,虽然语法与 Java 不同,但功能完全一致。这些操作通过 Int
和 Long
类型的扩展函数实现,除了取反使用 inv()
。
⚠️ 由于没有直接使用符号,初学者可能会觉得不够直观,但对于有经验的开发者来说,这种设计更有利于代码可读性和维护性。
位运算在以下领域非常有用:
- 高性能计算
- 信号处理
- 紧凑数据结构
- 权限/状态标志管理
所有示例代码可在 GitHub 上找到:GitHub 示例链接