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

时间:2016-12-08 08:27:06

标签: 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();
    }
}

知道为什么会这样吗?

5 个答案:

答案 0 :(得分: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);
}

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

答案 1 :(得分:53)

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

int i = 0x38e1036d;
int j = (int) 0x123438e1036dL;
i == j;

答案 2 :(得分:9)

第二个组件的位移&#39; 7527&#39;消除了您对第一个组件进行修改的效果&#39; 123438e1036d&#39;这导致生成相同的UUID。

第一个组件的处理本身是不同的,但是当uuid的第二个组件移位时,这种效果会丢失。

答案 3 :(得分:4)

这是因为它从右到左进行检查,只占用UUID的32个字符,并删除其他字符。一旦按顺序排列32个字符,它就不关心其他字符,因为它实现了Serializable接口。

public final class UUID
  extends Object
  implements Serializable, Comparable<UUID>

1234从你的第二个UUID裁剪。

这是它的代码,它有更好的帮助

 public static UUID More ...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);
    }

答案 4 :(得分:4)

这是2016年6月报道的Java 8中的已知错误: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8159339

另见http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8165199(2016年8月报道):

  

4d4d8f3b-3b81-44f3-968d-d1c1a48b4ac8是有效的UUID。

     

4d4d8f-3b3b81-44f3-968d-d1c1a48b4ac8不是(第一个破折号左移两个字符)

     

使用无效的UUID :: fromString()调用UUID代表004d4dbf-3b81-44f3-968d-d1c1a48b4ac8。