# Java UUID 生成器示例

> 原文： [https://howtodoinjava.com/java/basics/java-uuid/](https://howtodoinjava.com/java/basics/java-uuid/)

了解什么是 UUID 及其版本和变体。 学习使用`UUID.randomUUID()` API 在 Java 中生成 UUID。 另请学习用 Java 生成版本 5 UUID。

## 1\. 什么是 UUID？

**UUID** （*通用唯一标识符*），也称为 **GUID** （*全局唯一标识符*）是`128 bits`长标识符，相对于所有其他 UUID 的空间而言。 它不需要中央注册过程。 结果，按需生成可以完全自动化，并用于多种目的。

要了解 **UUID** 的独特性，您应该知道 UUID 生成算法支持非常高的分配速率，每台机器每秒可支持高达 *1000 万*的速度，因此甚至可以用作事务 ID。

我们可以应用排序，排序并将它们存储在数据库中。 通常，它在编程中很有用。

由于 UUID 是唯一且持久的，因此与其他替代方法相比，它们具有出色的*统一资源名称（URN）*，挖掘成本最低。

*空的 UUID（UHTID）是 UUID 的一种特殊形式，它指定将所有 128 位都设置为零。*

不要以为 UUID 很难猜测； 它们不应用作安全特性。 可预测的随机数源将加剧这种情况。 人类没有能力仅仅看一眼就能轻易地检查 UUID 的完整性。

## 2\. UUID 类型

典型的 UUID 以`8-4-4-4-12`的形式显示在 **5 组**中，由连字符分隔，总共 36 个字符（**32 个字母数字字符和 4 个连字符**）。

> `123e4567-e89b-12d3-a456-426655440000`
> 
> `xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx`

在此`'M'`表示 **UUID 版本**，`'N'`表示 **UUID 变体**。

*   **变体**字段包含一个值，该值标识 UUID 的布局。
*   **版本**字段包含一个描述此 UUID 类型的值。 UUID 有五种不同的基本类型。
    1.  基于时间的 UUID（版本 1） – 根据时间和节点 ID 生成
    2.  DCE（分布式计算环境）安全性（版本 2） – 由标识符（通常是组或用户 ID），时间和节点 ID 生成
    3.  基于名称（版本 3） – 由 [MD5](https://howtodoinjava.com/java/io/how-to-generate-sha-or-md5-file-checksum-hash-in-java/) （128 位）的名称空间标识符和名称的哈希值生成
    4.  随机生成的 UUID（版本 4） – 使用随机或伪随机数生成
    5.  基于名称的使用 SHA-1 哈希（版本 5）**推荐的** – 由 [SHA-1](https://howtodoinjava.com/security/how-to-generate-secure-password-hash-md5-sha-pbkdf2-bcrypt-examples/) （160 位）哈希处理的名称空间标识符和名称。 Java 不提供其实现。 我们将创造自己的。

## 3\. Java UUID 示例

#### 3.1 `UUID.randomUUID()` – 版本 4

默认 API [`randomUUID()`](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--)是一个静态工厂，用于检索类型 4（伪随机生成的）UUID。 对于大多数用例来说已经足够了。

```java
UUID uuid = UUID.randomUUID();

System.out.println(uuid);
System.out.println(uuid.variant());		//2
System.out.println(uuid.version());		//4

```

程序输出。

```java
17e3338d-344b-403c-8a87-f7d8006d6e33
2
4

```

#### 3.2 生成版本 5 UUID

Java 没有提供内置 API 来生成版本 5 UUID，因此我们必须创建自己的实现。 以下是一种这样的实现。 （[参考](https://github.com/rootsdev/polygenea/blob/master/java/src/org/rootsdev/polygenea/UUID5.java)）。

```java
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

public class UUID5 
{
	public static UUID fromUTF8(String name) {
		return fromBytes(name.getBytes(Charset.forName("UTF-8")));
	}

	private static UUID fromBytes(byte[] name) {
		if (name == null) {
			throw new NullPointerException("name == null");
		}
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			return makeUUID(md.digest(name), 5);
		} catch (NoSuchAlgorithmException e) {
			throw new AssertionError(e);
		}
	}

	private static UUID makeUUID(byte[] hash, int version) {
		long msb = peekLong(hash, 0, ByteOrder.BIG_ENDIAN);
		long lsb = peekLong(hash, 8, ByteOrder.BIG_ENDIAN);
		// Set the version field
		msb &= ~(0xfL << 12);
		msb |= ((long) version) << 12;
		// Set the variant field to 2
		lsb &= ~(0x3L << 62);
		lsb |= 2L << 62;
		return new UUID(msb, lsb);
	}

	private static long peekLong(final byte[] src, final int offset, final ByteOrder order) {
		long ans = 0;
		if (order == ByteOrder.BIG_ENDIAN) {
			for (int i = offset; i < offset + 8; i += 1) {
				ans <<= 8;
				ans |= src[i] & 0xffL;
			}
		} else {
			for (int i = offset + 7; i >= offset; i -= 1) {
				ans <<= 8;
				ans |= src[i] & 0xffL;
			}
		}
		return ans;
	}
}

```

```java
UUID uuid = UUID5.fromUTF8("954aac7d-47b2-5975-9a80-37eeed186527");

System.out.println(uuid);
System.out.println(uuid.variant());
System.out.println(uuid.version());

```

```java
d1d16b54-9757-5743-86fa-9ffe3b937d78
2
5

```

向我提供有关在 Java 中生成 UUID 的问题。

学习愉快！

参考： [Rfc 4122](https://tools.ietf.org/html/rfc4122)