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