无符号整数类型
除了整数类型之外,Kotlin 还提供了以下无符号整数类型:
类型 | 大小(位) | 最小值 | 最大值 |
---|---|---|---|
UByte | 8 | 0 | 255 |
UShort | 16 | 0 | 65,535 |
UInt | 32 | 0 | 4,294,967,295 (232 - 1) |
ULong | 64 | 0 | 18,446,744,073,709,551,615 (264 - 1) |
无符号类型支持其有符号对应类型的大多数操作。
无符号数以内联类的形式实现,含有一个单一的存储属性,该属性包含相同位宽的相应有符号对应类型。如果你想在无符号和有符号整数类型之间进行转换,请确保更新你的代码,以便任何函数调用和操作都支持新类型。
无符号数组与区间
无符号数组及其操作处于 Beta 阶段。它们随时可能发生不兼容的更改。 需要选择启用(参见下方详情)。
与原语类似,每种无符号类型都有一个表示该类型数组的对应类型:
UByteArray
: 无符号字节数组。UShortArray
: 无符号短整型数组。UIntArray
: 无符号整型数组。ULongArray
: 无符号长整型数组。
与有符号整数数组类似,它们提供与 Array
类类似的 API,且没有装箱开销。
当你使用无符号数组时,会收到一个警告,表明此特性尚未稳定。要消除该警告,请通过 @ExperimentalUnsignedTypes
注解选择启用。由你决定客户端是否必须显式选择启用你的 API 的使用,但请记住无符号数组不是一个稳定特性,因此使用它们的 API 可能会被语言变更破坏。有关选择启用要求的更多信息。
区间和数列由 UIntRange
、UIntProgression
、ULongRange
和 ULongProgression
类支持 UInt
和 ULong
。这些类与无符号整数类型一起都是稳定的。
无符号整数字面值
为了使无符号整数更易于使用,你可以向整数字面值附加后缀,以指示特定的无符号类型(类似于 Float
的 F
或 Long
的 L
):
u
和U
字母表示无符号字面值,但未指定确切类型。 如果未提供预期类型,编译器会根据字面值的大小使用UInt
或ULong
:kotlinval b: UByte = 1u // UByte,提供了预期类型 val s: UShort = 1u // UShort,提供了预期类型 val l: ULong = 1u // ULong,提供了预期类型 val a1 = 42u // UInt:未提供预期类型,常量适合 UInt val a2 = 0xFFFF_FFFF_FFFFu // ULong:未提供预期类型,常量不适合 UInt
uL
和UL
显式指定字面值应为无符号长整型:kotlinval a = 1UL // ULong,即使未提供预期类型且常量适合 UInt
用例
无符号数的主要用例是利用整数的完整位范围来表示正值。例如,表示不适合有符号类型的十六进制常量,例如 32 位 AARRGGBB
格式的颜色:
data class Color(val representation: UInt)
val yellow = Color(0xFFCC00CCu)
你可以使用无符号数初始化字节数组,无需显式 toByte()
字面值类型转换:
val byteOrderMarkUtf8 = ubyteArrayOf(0xEFu, 0xBBu, 0xBFu)
另一个用例是与原生 API 的互操作性。Kotlin 允许表示签名中包含无符号类型的原生声明。这种映射不会用有符号整数替换无符号整数,从而保持语义不变。
非目标
虽然无符号整数只能表示正数和零,但它们的用例并非应用领域需要非负整数的场景。例如,不将其用作集合大小或集合索引值的类型。
有几个原因:
- 使用有符号整数有助于检测意外溢出并发出错误条件信号,例如空 list 的
List.lastIndex
为 -1。 - 无符号整数不能被视为有符号整数的范围受限版本,因为它们的取值范围不是有符号整数范围的子集。有符号整数和无符号整数都不是彼此的子类型。