web-dev-qa-db-fra.com

L'UUID est le même à partir de différentes chaînes

J'ai deux chaînes différentes, mais après avoir analysé l'UUID, cela semble être le même

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

Une idée pourquoi c'est?

46
Jerry06

"123438e1036d-7527-42a3-98ca-f2f19d3155db"

Ce n'est pas un UUID. Il s'agit d'une chaîne concaténée de "1234" et d'un UUID. Le problème ici est que l'analyseur aurait dû vous le dire en lançant une exception. Au lieu de cela, il fait de son mieux pour trouver l'UUID enterré quelque part là-dedans.

Une fois que vous avez extrait l'UUID de votre chaîne concaténée, il est identique au premier UUID qui est le résultat correct que vous observez.

Nous pouvons analyser l'analyseur (merci à @ tim-biegeleisen d'avoir fourni le lien):

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

Comme nous pouvons le voir, il n'y a pas de validation sauf pour compter le nombre de groupes limités par des tirets. Il suffit de prendre ces groupes, puis de les déplacer vers des positions. Vous avez ajouté des personnages supplémentaires devant le premier groupe, ce qui est la partie la plus importante. Il est analysé et stocké en premier, puis il est déplacé de haut en bas jusqu'à ce qu'il occupe la partie la plus importante. Maintenant, tous les bits qui étaient plus à gauche que prévu sont poussés hors de la limite long, ils sont donc complètement ignorés.

68
Agent_L

Un UUID stocke 128 bits de données. Si vous lui donnez plus, il ne peut pas les stocker. Je suis surpris que cela ne vous donne pas d'erreur, mais pas surpris, sinon, il tronque les bits supérieurs.

int i = 0x38e1036d;
int j = (int) 0x123438e1036dL;
i == j;
53
Peter Lawrey

Le décalage de bits du deuxième composant "7527" supprime l'effet de la modification que vous avez apportée au premier composant "123438e1036d", ce qui entraîne la génération du même UUID.

Le traitement du premier composant en lui-même est différent mais cet effet est perdu lorsque le deuxième composant de l'uuid est déplacé.

9
UserF40

C'est parce qu'il vérifie de droite à gauche, ne prend que 32 caractères comme UUID et en supprime d'autres. une fois que 32 caractères dans l'ordre sont pris, il ne se soucie pas des autres, car il implémente l'interface sérialisable.

public final class UUID
  extends Object
  implements Serializable, Comparable<UUID>

1234 est supprimé de votre 2e UUID.

Voici son code, il aide beaucoup mieux

 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
Zubair Nabi

Il s'agit d'un bogue connu dans Java 8, signalé en juin 2016: http://bugs.Java.com/bugdatabase/view_bug.do?bug_id=8159339

Voir aussi http://bugs.Java.com/bugdatabase/view_bug.do?bug_id=8165199 (signalé en août 2016):

4d4d8f3b-3b81-44f3-968d-d1c1a48b4ac8 est un UUID valide.

4d4d8f-3b3b81-44f3-968d-d1c1a48b4ac8 n'est pas (déplacé les premiers tirets de deux caractères vers la gauche)

L'appel de UUID :: fromString () avec l'invalide entraîne un UUID représentant 004d4dbf-3b81-44f3-968d-d1c1a48b4ac8.

4
Fuad Efendi