日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java as uuid_java UUID 源码学习

發布時間:2023/12/31 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java as uuid_java UUID 源码学习 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

UUID

我們平時在使用 UUID 的時候覺得非常簡單,甚至很多人覺得這沒什么技術含量。

那么深入思考一層,UUID 的實現原理是什么?

源碼

類聲明

public final class UUID implements java.io.Serializable, Comparable {

/**

* Explicit serialVersionUID for interoperability.

*/

private static final long serialVersionUID = -4856846361193249489L;

}

實現了兩個常見的接口。

內部變量

/*

* The most significant 64 bits of this UUID.

*

* @serial

*/

private final long mostSigBits;

/*

* The least significant 64 bits of this UUID.

*

* @serial

*/

private final long leastSigBits;

/*

* The random number generator used by this class to create random

* based UUIDs. In a holder class to defer initialization until needed.

*/

private static class Holder {

static final SecureRandom numberGenerator = new SecureRandom();

}

前面2個時位定義。

下面一個 Holder 熟悉單例模式的都知道,這是通過內部靜態類,達到單例效果的一種寫法。

構造器

/**

* Constructs a new {@code UUID} using the specified data. {@code

* mostSigBits} is used for the most significant 64 bits of the {@code

* UUID} and {@code leastSigBits} becomes the least significant 64 bits of

* the {@code UUID}.

*

* @param mostSigBits

* The most significant bits of the {@code UUID}

*

* @param leastSigBits

* The least significant bits of the {@code UUID}

*/

public UUID(long mostSigBits, long leastSigBits) {

this.mostSigBits = mostSigBits;

this.leastSigBits = leastSigBits;

}

這個構造器非常簡單,就是做了下基本屬性的初始化。

還有一個私有的構造器,內容如下:

/*

* Private constructor which uses a byte array to construct the new UUID.

*/

private UUID(byte[] data) {

long msb = 0;

long lsb = 0;

assert data.length == 16 : "data must be 16 bytes in length";

for (int i=0; i<8; i++)

msb = (msb << 8) | (data[i] & 0xff);

for (int i=8; i<16; i++)

lsb = (lsb << 8) | (data[i] & 0xff);

this.mostSigBits = msb;

this.leastSigBits = lsb;

}

這個方法是直接根據 byte[] 數組內容初始化內部變量。

randomUUID()

這個方法是我們平時用的最多的

UUID.randomUUID().toString()

下面我們一起來看一下這個 randomUUID() 的真面目

/**

* Static factory to retrieve a type 4 (pseudo randomly generated) UUID.

*

* The {@code UUID} is generated using a cryptographically strong pseudo

* random number generator.

*

* @return A randomly generated {@code UUID}

*/

public static UUID randomUUID() {

SecureRandom ng = Holder.numberGenerator;

byte[] randomBytes = new byte[16];

ng.nextBytes(randomBytes);

randomBytes[6] &= 0x0f; /* clear version */

randomBytes[6] |= 0x40; /* set to version 4 */

randomBytes[8] &= 0x3f; /* clear variant */

randomBytes[8] |= 0x80; /* set to IETF variant */

return new UUID(randomBytes);

}

這里首先通過前面的內部靜態類,獲取一個單例的隨機數生成器。

然后做了 2 個位置的內容變換處理,這個需要一定的位運算知識。

最后在調用前面提到的構造器。

nameUUIDFromBytes(byte[])

/**

* Static factory to retrieve a type 3 (name based) {@code UUID} based on

* the specified byte array.

*

* @param name

* A byte array to be used to construct a {@code UUID}

*

* @return A {@code UUID} generated from the specified array

*/

public static UUID nameUUIDFromBytes(byte[] name) {

MessageDigest md;

try {

md = MessageDigest.getInstance("MD5");

} catch (NoSuchAlgorithmException nsae) {

throw new InternalError("MD5 not supported", nsae);

}

byte[] md5Bytes = md.digest(name);

md5Bytes[6] &= 0x0f; /* clear version */

md5Bytes[6] |= 0x30; /* set to version 3 */

md5Bytes[8] &= 0x3f; /* clear variant */

md5Bytes[8] |= 0x80; /* set to IETF variant */

return new UUID(md5Bytes);

}

這里是初始化了一個 MD5 的算法類。

后面的處理和上一個方法就類似了。

fromString(String)

源碼如下:

/**

* Creates a {@code UUID} from the string standard representation as

* described in the {@link #toString} method.

*

* @param name

* A string that specifies a {@code UUID}

*

* @return A {@code UUID} with the specified value

*

* @throws IllegalArgumentException

* If name does not conform to the string representation as

* described in {@link #toString}

*

*/

public static UUID fromString(String name) {

String[] components = name.split("-");

if (components.length != 5)

throw new IllegalArgumentException("Invalid UUID string: "+name);

for (int i=0; i<5; i++)

components[i] = "0x"+components[i];

long mostSigBits = Long.decode(components[0]).longValue();

mostSigBits <<= 16;

mostSigBits |= Long.decode(components[1]).longValue();

mostSigBits <<= 16;

mostSigBits |= Long.decode(components[2]).longValue();

long leastSigBits = Long.decode(components[3]).longValue();

leastSigBits <<= 48;

leastSigBits |= Long.decode(components[4]).longValue();

return new UUID(mostSigBits, leastSigBits);

}

這個方法我覺得應該和 toString() 結合起來看,這2個方法應該互為逆過程。

toString()

/**

* Returns a {@code String} object representing this {@code UUID}.

*

*

The UUID string representation is as described by this BNF:

*

* {@code

* UUID = "-" "-"

* "-"

* "-"

*

* time_low = 4*

* time_mid = 2*

* time_high_and_version = 2*

* variant_and_sequence = 2*

* node = 6*

* hexOctet =

* hexDigit =

* "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

* | "a" | "b" | "c" | "d" | "e" | "f"

* | "A" | "B" | "C" | "D" | "E" | "F"

* }

*

* @return A string representation of this {@code UUID}

*/

public String toString() {

return (digits(mostSigBits >> 32, 8) + "-" +

digits(mostSigBits >> 16, 4) + "-" +

digits(mostSigBits, 4) + "-" +

digits(leastSigBits >> 48, 4) + "-" +

digits(leastSigBits, 12));

}

digits()

這里就是把數字轉換為 16 進制

/** Returns val represented by the specified number of hex digits. */

private static String digits(long val, int digits) {

long hi = 1L << (digits * 4);

return Long.toHexString(hi | (val & (hi - 1))).substring(1);

}

感觸

看完之后,是不是覺得并沒有得到精髓呢?

我覺得算法的原理不清楚,單獨看了下源碼,實際上有些問題還是沒有解決。

為什么 UUID 可以保證唯一性?

如何實現自己的,位數更少的 id 算法?

關于這部分將在其他文章中進行補充完善。

拓展閱讀

參考資料

jdk8 源碼

總結

以上是生活随笔為你收集整理的java as uuid_java UUID 源码学习的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。