9.1.6 UUID
原文链接: https://kotlinlang.org/docs/uuids.html
9.1.6 UUID
Uuid 类表示通用唯一标识符(UUID),也称为全局唯一标识符(GUID)。
Uuid 是一个 128 位的值,用于唯一标识某个实体,而无需依赖集中分配 ID 的系统。这让 UUID 在分布式应用、数据库、客户端生成的记录或 Kotlin Multiplatform 应用中非常有用。
使用 Uuid 类来处理 UUID 值。与普通字符串不同,专用的 UUID 类型让代码更明确,并可防止误用无效的值。
要在项目中使用 UUID,请从 kotlin.uuid 包中导入 Uuid 类:
1
| import kotlin.uuid.Uuid
|
生成 UUID
要为常规标识符(例如用户 ID 或数据库 ID)生成随机的版本 4 UUID,请使用 Uuid.random() 函数:
1
2
3
4
5
6
| import kotlin.uuid.Uuid
fun main() {
val id = Uuid.random()
println(id)
}
|
你还可以用以下实验性函数生成特定版本的 UUID:
这些 UUID 生成函数是实验性的。要选择启用,请使用 @OptIn(ExperimentalUuidApi::class) 注解,或在构建文件中添加以下编译器选项:
Gradle
1
2
3
4
5
| kotlin {
compilerOptions {
freeCompilerArgs.add("-opt-in=kotlin.uuid.ExperimentalUuidApi")
}
}
|
Maven
1
2
3
4
5
6
7
8
9
10
11
12
13
| <build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-opt-in=kotlin.uuid.ExperimentalUuidApi</arg>
</args>
</configuration>
</plugin>
</plugins>
</build>
|
下面是一个生成特定版本 UUID 的示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| import kotlin.time.Instant
import kotlin.time.ExperimentalTime
import kotlin.uuid.Uuid
@OptIn(kotlin.uuid.ExperimentalUuidApi::class, ExperimentalTime::class)
fun main() {
// 生成一个版本 4 UUID
val idVersion4 = Uuid.generateV4()
println(idVersion4)
// 生成一个版本 7 UUID
val idVersion7 = Uuid.generateV7()
println(idVersion7)
// 为指定的时间戳生成一个版本 7 UUID
val timestamp = Instant.fromEpochMilliseconds(1757440583000L)
val idVersion7SpecificTime = Uuid.generateV7NonMonotonicAt(timestamp)
println(idVersion7SpecificTime)
}
|
解析 UUID
UUID 值通常表示为字符串,例如在 URL 参数或数据库记录中。
要把 String 值转换为 Uuid 值,请使用 Uuid.parse() 函数:
1
2
3
4
5
6
| import kotlin.uuid.Uuid
fun main() {
val id = Uuid.parse("de2bc56c-ea73-4f3c-8a37-5a46fdb2d79a")
println(id)
}
|
Uuid.parse() 函数既接受标准的十六进制加连字符格式,也接受不带连字符的十六进制格式。
如果输入无效,Uuid.parse() 函数会抛出 IllegalArgumentException:
1
2
3
4
5
6
| import kotlin.uuid.Uuid
fun main() {
val id = Uuid.parse("10")
println(id)
}
|
如果你的应用只接受一种表示形式,请使用特定格式的函数:
例如:
1
2
3
4
5
6
7
8
9
| import kotlin.uuid.Uuid
fun main() {
val standard = Uuid.parseHexDash("de2bc56c-ea73-4f3c-8a37-5a46fdb2d79a")
val compact = Uuid.parseHex("de2bc56cea734f3c8a375a46fdb2d79a")
println(standard)
println(compact)
}
|
如果你有来自外部的 UUID,并且必须安全地处理无效输入,请使用 Uuid.parseOrNull()、Uuid.parseHexDashOrNull() 或 Uuid.parseHexOrNull()。这些函数在输入无效时返回 null:
1
2
3
| fun parseId(input: String): Uuid? {
return Uuid.parseOrNull(input)
}
|
把 UUID 转换为字符串
你可以用以下函数把 Uuid 值转换为 String 值:
例如:
1
2
3
4
5
6
7
8
9
10
11
12
| import kotlin.uuid.Uuid
fun main() {
val id = Uuid.parse("de2bc56c-ea73-4f3c-8a37-5a46fdb2d79a")
println(id.toString())
// de2bc56c-ea73-4f3c-8a37-5a46fdb2d79a
println(id.toHexDashString())
// de2bc56c-ea73-4f3c-8a37-5a46fdb2d79a
println(id.toHexString())
// de2bc56cea734f3c8a375a46fdb2d79a
}
|
比较 UUID
你可以用 == 运算符检查 Uuid 值是否相等。
Kotlin 根据 UUID 的值来比较,而不是根据其文本表示。例如,只要两种不同形式表示的是同一个 128 位值,它们就相等:
1
2
3
4
5
6
7
8
9
| import kotlin.uuid.Uuid
fun main() {
val first = Uuid.parse("de2bc56c-ea73-4f3c-8a37-5a46fdb2d79a")
val second = Uuid.parse("de2bc56cea734f3c8a375a46fdb2d79a")
println(first == second)
// true
}
|
这使 Uuid 比较比字符串比较更可靠,因为字符串比较会把同一值的不同格式视为不同的值。Uuid 比较检查的是实际的标识符值。
Uuid 实现了 Comparable<Uuid> 接口,因此 UUID 值可以用 sorted() 等标准集合函数排序。在这种情况下,Kotlin 按字典序比较(从最高位到最低位):
1
2
3
4
5
6
7
8
9
| import kotlin.uuid.Uuid
fun main() {
val first = Uuid.generateV7()
val second = Uuid.generateV7()
val sorted = listOf(first, second).sorted()
println(sorted)
}
|
处理二进制表示
某些 API、存储格式和二进制协议并不把 UUID 表示为字符串,而是把 128 位的 UUID 值存储为以下形式之一:
当你需要与期望二进制 UUID 数据的系统交换 UUID 时,请使用这些表示形式。
要在 UUID 与 16 字节表示之间转换,请使用 .toByteArray() 和 Uuid.fromByteArray() 函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| import kotlin.uuid.Uuid
fun main() {
val id = Uuid.random()
val bytes = id.toByteArray()
val original = Uuid.fromByteArray(bytes)
println(id)
println(bytes)
println(original)
println(id == original)
// true
}
|
你也可以把同一个 128 位 UUID 值表示为两个 Long 值。这很有用,因为 Kotlin 没有内置的 128 位整数类型。这两个 Long 值分两部分存储 UUID:
mostSignificantBits 参数用于 UUID 的前 64 位。leastSignificantBits 参数用于 UUID 的后 64 位。
要从两个 Long 值创建 Uuid 值,请使用 Uuid.fromLongs() 函数:
1
2
3
4
5
6
7
8
9
10
| import kotlin.uuid.Uuid
fun main() {
val id = Uuid.fromLongs(
mostSignificantBits = -4653685776373167443,
leastSignificantBits = -6288180676521310383.toLong()
)
println(id)
// bf6ac971-52fd-4aad-a8bb-e4fdac78c751
}
|
要从现有的 Uuid 值中提取这两部分,请使用 Uuid.toLongs() 函数:
1
2
3
4
5
6
7
8
9
10
| import kotlin.uuid.Uuid
fun main() {
val id = Uuid.random()
id.toLongs { mostSignificantBits, leastSignificantBits ->
println(mostSignificantBits)
println(leastSignificantBits)
}
}
|
序列化 UUID
Kotlin 支持对 Uuid 值进行序列化。你可以用它把 UUID 值存储或传输到 Kotlin 代码之外,例如在 JSON API 或配置文件中。
要序列化 Uuid 值,除非你的应用需要其他格式,否则请把它表示为字符串。kotlinx.serialization 库使用十六进制加连字符格式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| import kotlin.uuid.Uuid
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
@Serializable
data class User(
val id: Uuid,
val name: String
)
fun main() {
val user = User(
id = Uuid.parse("de2bc56cea734f3c8a375a46fdb2d79a"),
name = "Kotlin"
)
println(Json.encodeToString(user))
// {"id":"de2bc56c-ea73-4f3c-8a37-5a46fdb2d79a","name":"Kotlin"}
}
|
与 Java API 一起使用 UUID
Java 使用 java.util.UUID 类表示 UUID。在 JVM 上,Java API 可能接受或返回这种类型。虽然 java.util.UUID 和 kotlin.uuid.Uuid 都表示 UUID,但它们是两种不同的类型。
在 Kotlin 与 Java 之间传递 UUID 时,请显式转换值:
1
2
3
| import kotlin.uuid.toKotlinUuid
val kotlinId: Uuid = javaId.toKotlinUuid()
|
1
2
3
| import kotlin.uuid.toJavaUuid
val javaId: java.util.UUID = kotlinId.toJavaUuid()
|
这些函数让你可以在 JVM 互操作边界上使用 Uuid 来表示 UUID 值。
注意: java.util.UUID 和 kotlin.uuid.Uuid 类可以比较,但顺序可能不同。从 Java API 迁移到 Kotlin API 之前,请务必检查依赖 UUID 顺序的代码。
Kotlin 还提供了对 Java 缓冲区的支持。使用 JVM 特有的函数在 ByteBuffer 中处理 UUID: