天天看点

UUID原理以及使用普通调用:浅析普通调用原理:

普通调用:

不用导包,直接写了全路径

public static String generatorUUIDAndReplace(Boolean replace){
        String uuid = java.util.UUID.randomUUID().toString();
        if(replace){
            uuid = uuid.replaceAll("-","");
        }
        return uuid;
    }
           

传值true则去除-,传值false保留-

浅析普通调用原理:

点到randomUUID()方法里面可以看到

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);
    }
           

打个断点查看一下流程

UUID原理以及使用普通调用:浅析普通调用原理:

可以看出

SecureRandom ng = Holder.numberGenerator;
        byte[] randomBytes = new byte[16];
           

这两句代码是创建一个16位的byte数组,后续代码赋值。

UUID原理以及使用普通调用:浅析普通调用原理:

说明了

这句代码是给byte数组赋值的。

UUID原理以及使用普通调用:浅析普通调用原理:

这里只是将byte数组设置为版本4,并设置为IETF变体;

点开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;
    }
           

使用字节数组构造新UUID的私有构造函数。这里有两个属性值mostSigBits和leastSigBits在toString()方法里面有调用。点进去可以看到

public String toString() {
        return (digits(mostSigBits >> 32, 8) + "-" +
                digits(mostSigBits >> 16, 4) + "-" +
                digits(mostSigBits, 4) + "-" +
                digits(leastSigBits >> 48, 4) + "-" +
                digits(leastSigBits, 12));
    }
           

将uuid对象转换成uuid格式的字符串,点进digits方法里面

private static String digits(long val, int digits) {
        long hi = 1L << (digits * 4);
        return Long.toHexString(hi | (val & (hi - 1))).substring(1);
    }
           

digits方法的作用是返回由指定数量的十六进制数字表示的val。toHexString将Long类型转换成字符串类型,substring是切割字符串用的,这里是除去第一个字符

最后,看一下是怎么生成随机byte数组的:

通过 ng.nextBytes(randomBytes); 可以点进去看到

public synchronized void engineNextBytes(byte[] var1) {
        int var2 = 0;
        byte[] var4 = this.remainder;
        if (this.state == null) {
            byte[] var5 = new byte[20];
            SecureRandom.SeederHolder.seeder.engineNextBytes(var5);
            this.state = this.digest.digest(var5);
        }

        int var7 = this.remCount;
        int var3;
        int var6;
        if (var7 > 0) {
            var3 = var1.length - var2 < 20 - var7 ? var1.length - var2 : 20 - var7;

            for(var6 = 0; var6 < var3; ++var6) {
                var1[var6] = var4[var7];
                var4[var7++] = 0;
            }

            this.remCount += var3;
            var2 += var3;
        }

        while(var2 < var1.length) {
            this.digest.update(this.state);
            var4 = this.digest.digest();
            updateState(this.state, var4);
            var3 = var1.length - var2 > 20 ? 20 : var1.length - var2;

            for(var6 = 0; var6 < var3; ++var6) {
                var1[var2++] = var4[var6];
                var4[var6] = 0;
            }

            this.remCount += var3;
        }

        this.remainder = var4;
        this.remCount %= 20;
    }