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.out.println(t1.toString().equals(t2.toString()));
} catch (Exception e) {
e.printStackTrace();
}
}
Любая идея, почему это так?
Ответы
Ответ 1
"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
, поэтому они полностью игнорируются.
Ответ 2
A UUID хранит 128 бит данных. Если вы дадите больше, они не смогут их хранить. Я удивлен, что это не дает вам ошибки, но не удивляет, что в противном случае обрезает более высокие бит.
int i = 0x38e1036d;
int j = (int) 0x123438e1036dL;
i == j;
Ответ 3
Смещение бит второго компонента "7527" устраняет эффект внесенной вами модификации в первый компонент "123438e1036d", в результате чего генерируется тот же самый UUID.
Обработка первого компонента сама по себе различна, но этот эффект теряется при смещении второго компонента uuid.
Ответ 4
Это потому, что он проверяет справа налево и занимает всего 32 символа как UUID и удаляет другие. как только 32 символа в порядке, он не заботится о других, так как он реализует интерфейс Serializable.
public final class UUID
extends Object
implements Serializable, Comparable<UUID>
1234 обрезается от вас 2-м 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);
}
Ответ 5
Это известная ошибка в Java 8, о которой сообщалось в июне 2016 года:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8159339
См. также http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8165199 (сообщается в августе 2016 года):
4d4d8f3b-3b81-44f3-968d-d1c1a48b4ac8 - действительный UUID.
4d4d8f-3b3b81-44f3-968d-d1c1a48b4ac8 нет (перемещен первый штрих два символа влево)
Вызов UUID:: fromString() с недопустимым приводит к UUID, представляющему 004d4dbf-3b81-44f3-968d-d1c1a48b4ac8.