# UUID
[Uuid](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/) 类表示通用唯一标识符 (Universally Unique Identifier, UUID), 也称为全局唯一标识符 (Globally Unique Identifier, GUID).
`Uuid` 是一个 128 位的值, 用于在不依赖集中式 ID 分配系统的情况下, 唯一标识一个实体. 这使得 UUID 在分布式应用程序, 数据库, 客户端生成的记录, 或 [Kotlin Multiplatform](get-started.html) 应用程序中非常有用.
请使用 `Uuid` 类来处理 UUID 值. 与普通字符串不同, 专用的 UUID 类型能够让你的代码更加明确, 并防止意外使用无效的值.
要在你的项目中使用 UUID, 请从 `kotlin.uuid` 包导入 `Uuid` 类:
```KOTLIN
import kotlin.uuid.Uuid
```
## 生成 UUID
要生成一个随机的版本 4 的 UUID 用做通常的标识符 (例如用户或数据库 ID), 请使用 [Uuid.random()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/random.html) 函数:
```KOTLIN
import kotlin.uuid.Uuid
fun main() {
//sampleStart
val id = Uuid.random()
println(id)
//sampleEnd
}
```
你还可以使用以下 [实验性](components-stability.html#stability-levels-explained) 函数, 生成特定版本的 UUID:
* [Uuid.generateV4()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/generate-v4.html) 函数, 生成与 `Uuid.random()` 函数相同类型的 UUID, 但明确指明返回值是版本 4 的 UUID.
* [Uuid.generateV7()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/generate-v7.html) 函数, 生成版本 7 的 UUID, 带有时间戳, 可用于 UUID 排序.
* [Uuid.generateV7NonMonotonicAt()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/generate-v7-non-monotonic-at.html) 函数, 为特定时刻生成版本 7 的 UUID.
这些 UUID 生成函数是实验性的. 要选择使用者同意, 请使用 `@OptIn(ExperimentalUuidApi::class)` 注解, 或在你的构建文件中添加以下编译器选项:
Gradle:
```KOTLIN
kotlin {
compilerOptions {
freeCompilerArgs.add("-opt-in=kotlin.uuid.ExperimentalUuidApi")
}
}
```
Maven:
```XML
org.jetbrains.kotlin
kotlin-maven-plugin
-opt-in=kotlin.uuid.ExperimentalUuidApi
```
下面的示例生成指定版本的 UUID:
```KOTLIN
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()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/parse.html) 函数:
```KOTLIN
import kotlin.uuid.Uuid
fun main() {
//sampleStart
val id = Uuid.parse("de2bc56c-ea73-4f3c-8a37-5a46fdb2d79a")
println(id)
//sampleEnd
}
```
`Uuid.parse()` 函数接受标准的 16 进制加横线分隔符格式, 以及不带横线分隔符的 16 进制格式.
如果输入无效, `Uuid.parse()` 函数会抛出 `IllegalArgumentException` 异常:
```KOTLIN
import kotlin.uuid.Uuid
fun main() {
//sampleStart
val id = Uuid.parse("10")
println(id)
//sampleEnd
}
```
如果你的应用程序只接受一种表示形式, 请使用特定格式的函数:
* [Uuid.parseHexDash()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/parse-hex-dash.html), 用于 16 进制加横线分隔符的字符串表示.
* [Uuid.parseHex()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/parse-hex.html), 用于不带横线分隔符的 16 进制字符串表示.
例如:
```KOTLIN
import kotlin.uuid.Uuid
fun main() {
//sampleStart
val standard = Uuid.parseHexDash("de2bc56c-ea73-4f3c-8a37-5a46fdb2d79a")
val compact = Uuid.parseHex("de2bc56cea734f3c8a375a46fdb2d79a")
println(standard)
println(compact)
//sampleEnd
}
```
如果你有来自外部来源的 UUID, 并且必须安全地处理无效输入, 请使用 [Uuid.parseOrNull()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/parse-or-null.html), [Uuid.parseHexDashOrNull()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/parse-hex-dash-or-null.html), 或 [Uuid.parseHexOrNull()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/parse-hex-or-null.html) 函数. 这些函数在输入无效时会返回 `null`:
```KOTLIN
fun parseId(input: String): Uuid? {
return Uuid.parseOrNull(input)
}
```
## 将 UUID 转换为字符串
你可以使用以下函数, 将 `Uuid` 值转换为 `String` 值:
* [toString()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/to-string.html) 用于标准字符串表示
* [toHexDashString()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/to-hex-dash-string.html) 用于 16 进制加横线分隔符格式
* [toHexString()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/to-hex-string.html) 用于不带横线分隔符的 16 进制格式
例如:
```KOTLIN
import kotlin.uuid.Uuid
fun main() {
//sampleStart
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
//sampleEnd
}
```
## 比较 UUID
你可以使用 `==` 运算符, 检查 `Uuid` 值是否相等.
Kotlin 根据 UUID 值进行比较, 而不是根据文本表示. 例如, 如果不同形式的两个值表示相同的 128 位值, 则判定为相等:
```KOTLIN
import kotlin.uuid.Uuid
fun main() {
//sampleStart
val first = Uuid.parse("de2bc56c-ea73-4f3c-8a37-5a46fdb2d79a")
val second = Uuid.parse("de2bc56cea734f3c8a375a46fdb2d79a")
println(first == second)
// 输出结果为: true
//sampleEnd
}
```
这使得 `Uuid` 的比较比字符串比较更可靠, 因为字符串比较会将相同值的不同格式视为不同. `Uuid` 比较检查的是实际的标识符值.
`Uuid` 实现了 `Comparable` 接口, 因此 UUID 值可以使用标准的集合函数(例如 `sorted()`) 进行排序. 在这种情况下, Kotlin 按字典序比较值 (从最高有效位到最低有效位):
```KOTLIN
import kotlin.uuid.Uuid
fun main() {
//sampleStart
val first = Uuid.generateV7()
val second = Uuid.generateV7()
val sorted = listOf(first, second).sorted()
println(sorted)
//sampleEnd
}
```
## 使用二进制表达
某些 API, 存储格式, 以及二进制协议, 不以字符串形式表示 UUID. 相反, 它们将 128 位 UUID 值存储为:
* 16 字节数组
* 两个 64 位值
当你需要与期望二进制 UUID 数据的系统交换 UUID 时, 请使用这些表达.
要在 UUID 和 16 字节表达之间进行转换, 请使用 [.toByteArray()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/to-byte-array.html) 和 [Uuid.fromByteArray()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/from-byte-array.html) 函数:
```KOTLIN
import kotlin.uuid.Uuid
fun main() {
//sampleStart
val id = Uuid.random()
val bytes = id.toByteArray()
val original = Uuid.fromByteArray(bytes)
println(id)
println(bytes)
println(original)
println(id == original)
// 输出结果为: true
//sampleEnd
}
```
也可以将相同的 128 位 UUID 值表示为 2 个 `Long` 值. 这很有用, 因为 Kotlin 没有提供内置的 128 位整数类型. 这 2 个 `Long` 值将 UUID 分为 2 部分存储:
* `mostSignificantBits` 参数, 存储 UUID 的前 64 位.
* `leastSignificantBits` 参数, 存储 UUID 的后 64 位.
要从 2 个 `Long` 值创建 `Uuid` 值, 请使用 [Uuid.fromLongs()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/-companion/from-longs.html) 函数:
```KOTLIN
import kotlin.uuid.Uuid
fun main() {
//sampleStart
val id = Uuid.fromLongs(
mostSignificantBits = -4653685776373167443,
leastSignificantBits = -6288180676521310383.toLong()
)
println(id)
// 输出结果为: bf6ac971-52fd-4aad-a8bb-e4fdac78c751
//sampleEnd
}
```
要从现有的 `Uuid` 值中提取 2 个部分, 请使用 [Uuid.toLongs()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/-uuid/to-longs.html) 函数:
```KOTLIN
import kotlin.uuid.Uuid
fun main() {
//sampleStart
val id = Uuid.random()
id.toLongs { mostSignificantBits, leastSignificantBits ->
println(mostSignificantBits)
println(leastSignificantBits)
}
//sampleEnd
}
```
## 序列化 UUID
Kotlin 支持对 `Uuid` 值进行序列化. 使用这个功能, 可以在 Kotlin 代码之外存储或传输 UUID 值, 例如在 JSON API 中, 或在配置文件中.
要序列化 `Uuid` 值, 请将其表示为字符串, 除非你的应用程序需要其他格式. [kotlinx.serialization](https://kotlinlang.org/docs/serialization.html) 库使用 16 进制加横线分隔符格式:
```KOTLIN
//sampleStart
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"}
}
//sampleEnd
```
## 在 Java API 中使用 UUID
Java 使用 `java.util.UUID` 类来表示 UUID. 在 JVM 上, Java API 可能接受或返回此类型. 尽管 `java.util.UUID` 和 `kotlin.uuid.Uuid` 都表示 UUID, 但它们是两种不同的类型.
要在 Kotlin 和 Java 之间传递 UUID, 请进行明确的转换:
* 使用 [.toKotlinUuid()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/to-kotlin-uuid.html) 扩展函数, 将 Java UUID 转换为 Kotlin: ```KOTLIN import kotlin.uuid.toKotlinUuid val kotlinId: Uuid = javaId.toKotlinUuid() ```
* 使用 [.toJavaUuid()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/to-java-uuid.html) 扩展函数, 将 Kotlin UUID 转换为 Java: ```KOTLIN import kotlin.uuid.toJavaUuid val javaId: java.util.UUID = kotlinId.toJavaUuid() ```
通过这些函数, 你可以在 JVM 互操作边界处使用 `Uuid` 来表示 UUID 值.
> **Note:**
> `java.util.UUID` 和 `kotlin.uuid.Uuid` 类可以进行比较, 但排序方式可能不同. 在从 Java API 迁移到 Kotlin API 之前, 请确保检查那些依赖于 UUID 排序的代码.
Kotlin 还提供了对 Java 缓冲区的支持. 请使用 JVM 专用的函数, 在 `ByteBuffer` 中操作 UUID:
* 使用 [.getUuid()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/get-uuid.html) 函数, 从缓冲区读取 UUID.
* 使用 [.putUuid()](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.uuid/put-uuid.html) 函数, 将 UUID 写入缓冲区.