为什么两个不同的 java.util.UUID 对象比较相等?

Why are two different java.util.UUID objects comparing as equal?

我创建了两个 java.util.UUID 实例,如下所示。一个是从 UUID.randomUUID() 创建的,另一个是相同的,但在开头添加了一些额外的数字。当使用 UUID.equals 方法比较它们时 returns true:

UUID uuid1 = UUID.randomUUID();
UUID uuid2 = UUID.fromString("12345"+uuid1.toString());
System.out.println(uuid1.equals(uuid2));  // this gives true.

我认为添加的数字被丢弃了,并且都给出了相同的 UUID 字符串值。为什么会这样?

因为您没有创建两个不同的 UUID。

UUID.fromString("12345"+uuid1.toString()); 没有意义:UUID.fromString(String) 要求传递的字符串遵守 'string standard representation',如 UUID.toString() 中所述。参见 UUID.fromString() and UUID.toString()

我想知道为什么你不会得到异常,但我想你的前几个字符被忽略了。

在 UUID.fromString(...) 方法中你有这个:

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

它做的第一件事是将 UUID 的各个部分分离成组件,然后它会创建两个 long。在这里,您通过添加前导字符仅更改了 UUID 的第一个组件,您的 UUID 字符串例如为“12345894ff97a-039b-47fe-8a72-950b7766d50c”。所以第一个组件是“12345894ff97a”,当它会做

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

然后你将得到“320256540146042”,实际的 HEX 表示是“12345894ff97a”,然后你有一个位操作,将长 16 位向左移动:

mostSigBits <<= 16;

这将导致“2541588541301456896”,实际的十六进制表示为“2345894ff97a0000”(我们移动了 16 位,所以 4 个十六进制字符),您开始看到发生了什么,看到 long 格式只有 64 位,所以在移动位时会丢失一些,这里第一个字符“1”丢失了。之后,在释放的 space 中,它将添加第二个组件:

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

这将导致“2541588541301457819”,实际的 HEX 表示为“2345894ff97a039b”,然后它将长 16 位再次向左移动:

mostSigBits <<= 16;

这将导致“-8552342864911466496”,实际的 HEX 表示为“894ff97a039b0000”,由于 64 位长,这里您的前导字符全部丢失。

我不需要解释其余的方法(最后 mostSigBits 是“894ff97a039b47fe”,leastSigBits 是“8a72950b7766d50c”),你已经可以理解添加到 UUID 的任何前导字符都会丢失调用 UUID.fromString(..) 因为只考虑最后 8 个十六进制字符(32 位),其余的将丢失。