Skip to content

无符号数与位运算

源:Kotlin standard library - Unsigned types, Bitwise operations

在处理低级编程(如网络协议、二进制格式解析、加密算法或图形渲染)时,位运算和无符号整数是不可或缺的工具。Kotlin 1.5 正式引入了稳定的无符号整数支持。

无符号整数 (Unsigned Integers) Kotlin 1.5+

Kotlin 提供了四种无符号类型:UByte (8位), UShort (16位), UInt (32位), ULong (64位)。

定义与字面量

使用 uuL 后缀来定义无符号数值。

kotlin
val uByte: UByte = 255u
val uInt = 4000000000u
val uLong = 10000000000000000000uL

// 十六进制也非常常用
val flag = 0xFFu

转换与陷阱

无符号数与有符号数之间的转换是通过二进制位直接重新解释实现的,这可能会导致意想不到的结果。

kotlin
val signedInt: Int = -1
val unsignedInt: UInt = signedInt.toUInt()

println(unsignedInt) // 4294967295 (即 UInt.MAX_VALUE)

兼容性提示

无符号类型在 JVM 上是通过 Inline Class 实现的,虽然它们在性能上接近原生类型,但在与 Java 互操作时需要特别注意,因为 Java 并不原生支持无符号类型(Java 会看到对应的有符号类型和混淆后的名称)。

位运算 (Bitwise Operations)

不同于 Java 使用符号(如 <<, &),Kotlin 使用中缀函数 (Infix Functions) 来进行位运算,这使得代码读起来更像自然语言。

核心操作符

操作函数说明Java 等价
左移shlShift Left<<
右移shrShift Right (带符号)>>
无符号右移ushrUnsigned Shift Right>>>
andBitwise AND&
orBitwise OR|
异或xorBitwise XOR^
取反invBitwise Inversion~

实战示例:解析标志位 (Flags)

kotlin
// 定义权限标志
val READ = 1 shl 0    // 0001
val WRITE = 1 shl 1   // 0010
val EXECUTE = 1 shl 2 // 0100

var myPermission = READ or WRITE // 0011

// 检查是否有写权限
val hasWrite = (myPermission and WRITE) != 0

// 移除读权限
myPermission = myPermission and READ.inv()

位操作进阶:二进制转换

kotlin
val number = 42

// 转换为二进制字符串
println(number.toString(2)) // "101010"

// 转换为十六进制字符串
println(number.toString(16)) // "2a"

// 从二进制字符串解析
val fromBinary = "101010".toInt(2)

无符号数组 (Unsigned Arrays)

为了性能优化,Kotlin 还提供了专门的无符号数组类型,避免了装箱开销。

kotlin
val pixels = UIntArray(1024) { 0u }
pixels[0] = 0xFF0000u // 红色

性能与工程建议

  1. 优先使用位运算处理 Flag:在 Android 开发中,处理 View 的状态或自定义布局标志时,位运算比 Boolean 数组或 Set 性能更高、更节省内存。
  2. 谨慎用于业务逻辑:除非是在算法、协议解析或追求极致性能的底层模块,否则不要在普通业务逻辑中使用无符号数,因为它会增加代码理解成本和互操作复杂性。
  3. 注意溢出:无符号数的加减法同样会发生溢出,但在 Kotlin 中,无符号数的溢出行为是符合预期的(即模运算)。