46 votes

UUID est le même pour différentes chaînes

J'ai deux chaînes de caractères différentes, mais après les avoir analysées en UUID, elles semblent être identiques

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 de pourquoi?

68voto

Agent_L Points 1583

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

Ce n'est pas un UUID. C'est 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 en fait trouver l'UUID enfoui quelque part.

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

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

public static UUID fromString(String name) {
    String[] components = name.split("-");
    if (components.length != 5)
        throw new IllegalArgumentException("Chaîne UUID invalide : "+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 on peut le voir, il n'y a aucune validation sauf pour compter le nombre de groupes limités par des tirets. Il prend simplement ces groupes et les déplace ensuite dans les positions. Vous avez ajouté des caractères supplémentaires devant le premier groupe, qui est la partie la plus significative. Cela est analysé et stocké en premier, puis il est décalé vers le haut et encore vers le haut jusqu'à ce qu'il occupe la partie la plus significative. Maintenant, tous les bits qui étaient plus à gauche que prévu sont poussés hors de la limite du long, donc ils sont complètement ignorés.

53voto

Peter Lawrey Points 229686

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

int i = 0x38e1036d;
int j = (int) 0x123438e1036dL;
i == j;

9voto

UserF40 Points 2314

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 par lui-même est différent mais cet effet est perdu lorsque le deuxième composant de l'UUID est décalé.

4voto

Zubair Nabi Points 656

Cela est dû au fait qu'il vérifie de droite à gauche, et prend seulement 32 caractères comme UUID, et en supprime d'autres. une fois que les 32 caractères sont pris dans l'ordre, il ne se soucie pas des autres, car il implémente l'interface Serializable.

public final class UUID
  extends Object
  implements Serializable, Comparable

1234 est supprimé de votre 2ème UUID.

Voici son code, il est beaucoup plus utile

 public static UUID More ...fromString(String name) {
    String[] components = name.split("-");
    if (components.length != 5)
        throw new IllegalArgumentException("Chaîne UUID invalide : "+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);
    }

4voto

Fuad Efendi Points 99

Ceci est 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 ne l'est pas (déplacer les deux premiers tirets de deux caractères vers la gauche)

Appeler UUID::fromString() avec celui invalide donne un UUID représentant 004d4dbf-3b81-44f3-968d-d1c1a48b4ac8.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X