不同的字符串中的UUID是相同的

Vie*_*iet 46 java uuid

我有两个不同的字符串,但在解析为UUID后,它似乎是相同的

public static void main(String[] args) {
    try {
        UUID t1 = UUID.fromString("38e1036d-7527-42a3-98ca-f2f19d3155db");
        UUID t2 = UUID.fromString("123438e1036d-7527-42a3-98ca-f2f19d3155db");
        System.out.println(t1.toString().equals(t2.toString()));
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

知道为什么会这样吗?

Age*_*t_L 68

"123438e1036d-7527-42a3-98ca-f2f19d3155db"

这不是UUID.它是"1234"和UUID的串联字符串.这里的问题是解析器应该通过抛出异常告诉你这个.相反,它会尽力找到埋在那里的UUID.

从连接字符串中提取UUID后,它与第一个UUID相同,这是您正在观察的正确结果.

我们可以分析解析器(感谢@ tim-biegeleisen提供链接):

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);
}
Run Code Online (Sandbox Code Playgroud)

我们可以看到,除了计算由连字符限制的组数外,没有验证.它只需要那些组,然后将它们转移到位置.您在第一组前面添加了额外的字符,这是最重要的部分.它首先被解析和存储,然后再向上移动,直到它占据最重要的部分.现在,比假设更远的所有位都被推出long限制,因此它们被完全忽略.


Pet*_*rey 53

UUID存储128个比特的数据.如果你给它更多,它就无法存储它们.我很惊讶它没有给你一个错误,但不会惊讶它截断高位否则.

int i = 0x38e1036d;
int j = (int) 0x123438e1036dL;
i == j;
Run Code Online (Sandbox Code Playgroud)

  • 对于任何想要了解源代码实际执行情况的人:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/UUID.java# UUID.fromString%28java.lang.String 29% (7认同)

Use*_*F40 9

第二个组件'7527'的位移除了你对第一个组件'123438e1036d'所做的修改的效果,这导致生成相同的UUID.

第一个分量的处理本身是不同的,但是当uuid的第二个分量被移位时,这种影响就会消失.