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



我创建了两个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 的各个部分分成组件,然后它将创建两个长整型。在这里,您仅通过添加前导字符更改了 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",实际的十六进制表示为">2345894ff97a039b",然后它将再次将长 16 位向左移动:

mostSigBits <<= 16;

这将导致"-8552342864911466496",实际的十六进制表示形式是"894ff97a039b0000",并且由于 64 位大小较长,您的前导字符都丢失了。

我不需要解释该方法的其余部分(最后大多数SigBits是"894ff97a039b47fe",最小SigBits是"8a72950b7766d50c"),你已经可以理解,在调用UUID.fromString(..)时,添加到UUID的任何前导字符都将丢失,因为只考虑最后8个十六进制字符(32位),其余的将丢失。

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

UUID.fromString("12345"+uuid1.toString());没有意义:UUID.fromString(String)要求传递的 String 遵循UUID.toString()中所述的"字符串标准表示形式"。请参阅 UUID.fromString() 和 UUID.toString()。

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

最新更新