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

Java UUID在不同的字符串中是相同的,java,uuid,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

我有两个不同的字符串,但在解析到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();
    }
}
知道为什么吗?

A存储数据。如果你给它更多,它就无法储存它们。我很惊讶它没有给你一个错误,但不奇怪它会截断高位

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

第二个组件“7527”的位移位消除了您对第一个组件“123438e1036d”所做修改的影响,这将导致生成相同的UUID

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

“123438e1036d-7527-42a3-98ca-f2f19d3155db”

这不是UUID。它是一个由“1234”和UUID组成的串联字符串。这里的问题是解析器应该通过抛出异常来告诉您这一点。相反,它尽最大努力找到埋在那里的UUID

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

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

公共静态UUID fromString(字符串名称){
String[]components=name.split(“-”);
if(components.length!=5)
抛出新的IllegalArgumentException(“无效的UUID字符串:“+name”);

对于(int i=0;i,这是因为它从右到左检查,只接受32个字符作为UUID,并删除其他字符。一旦按顺序接受32个字符,它就不关心其他字符,因为它实现了可序列化接口

public final class UUID
  extends Object
  implements Serializable, Comparable<UUID>
公共最终类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);
    }
publicstaticuuid更多…fromString(字符串名称){
String[]components=name.split(“-”);
if(components.length!=5)
抛出新的IllegalArgumentException(“无效的UUID字符串:“+name”);

对于(int i=0;i这是Java 8中已知的错误,于2016年6月报告:

另见(2016年8月报道):

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

4d4d8f-3b3b81-44f3-968d-d1c1a48b4ac8未激活(将第一个破折号向左移动两个字符)

使用无效的UUID::fromString()调用UUID将导致一个表示004d4dbf-3b81-44f3-968d-d1c1a48b4ac8的UUID


你得到了什么输出?你期望得到什么输出?如果你打印这两个结果而不是比较它们,会发生什么?可能是因为UUID除了开始时的
1234
之外是完全相同的?如果你改变UUID的其余部分,而不是在开始时添加4位数字,会怎么样?听起来像是个bug。它应该会引发一些错误异常告诉您它不是一个有效的UUID。对于任何想要查看源代码实际在做什么的人来说:它被截断了,但当
mostSigBits
或“leatsigbits”超过64位时,我会为此提交一个bug。我对他们为什么这样做的最好猜测是,他们可能打算让UUID的每个部分都更短o是否不需要前导零?我不知道。如果它是“从左到右”并且“只需要32个字符”,那么
55db
将被忽略。但它不是…@Raedwald嗯,默认情况下存在的验证更多地是一个约定问题。我对Java不太了解,无法说出约定是什么。
 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);
    }