我创建了两个 java.util.UUID
实例,如下所示。一个是从 UUID.randomUUID()
创建的,另一个是相同的,但在开头添加了一些额外的数字。当使用 UUID.equals
方法比较它们时,它返回 true
:
UUID uuid1 = UUID.randomUUID();
UUID uuid2 = UUID.fromString("12345"+uuid1.toString());
System.out.println(uuid1.equals(uuid2)); // this gives true.
我认为添加的数字被丢弃了,并且都给出了相同的 UUID 字符串值。为什么会这样?
最佳答案
在 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”,实际的十六进制表示是“12345894ff97a”,然后你有一个位操作,将长 16 位向左移动:
mostSigBits <<= 16;
这将导致“2541588541301456896”,实际的十六进制表示为“2345894ff97a0000”(我们移动了 16 位,所以 4 个十六进制字符),您开始看到发生了什么,看到长格式是只有 64 位,所以在移动位时会丢失一些,这里第一个字符“1”丢失了。之后,在释放的空间中,它将添加第二个组件:
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 位),其余的将丢失。
关于java - 为什么两个不同的 java.util.UUID 对象比较相等?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44518355/