256 votes

Comment obtenir l'identifiant unique d'un objet qui surcharge hashCode() ?

Lorsqu'une classe en Java ne surcharge pas la fonction hashCode() , L'impression d'une instance de cette classe permet d'obtenir un numéro unique.

La Javadoc d'Object dit à peu près ceci hashCode() :

Dans la mesure du possible, la méthode hashCode définie par la classe Object renvoie des nombres entiers distincts pour des objets distincts.

Mais lorsque la classe remplace hashCode() Comment puis-je obtenir son numéro unique ?

38 votes

Principalement pour des raisons de "débogage" ;) Pour pouvoir dire : Ah, même objet !

6 votes

À cette fin, la fonction System.identityHashcode() est probablement utile. Cependant, je ne m'y fierais pas pour mettre en œuvre une fonctionnalité de code. Si vous souhaitez identifier les objets de manière unique, vous pouvez utiliser AspectJ et insérer un identifiant unique pour chaque objet créé. Plus de travail, cependant

9 votes

Gardez à l'esprit que l'unicité du hashCode n'est PAS garantie. Même si l'implémentation utilise l'adresse mémoire comme code de hachage par défaut. Pourquoi n'est-il pas unique ? Parce que les objets sont ramassés et que la mémoire est réutilisée.

386voto

Brian Agnew Points 143181

System.identityHashCode(votreObjet) donne le code de hachage "original" de votre objet sous la forme d'un entier. L'unicité n'est pas nécessairement garantie. L'implémentation de la JVM Sun vous donnera une valeur liée à l'adresse mémoire d'origine de cet objet, mais il s'agit d'un détail d'implémentation et vous ne devriez pas vous y fier.

EDIT : Réponse modifiée suite au commentaire de Tom ci-dessous concernant les adresses mémoire et les objets mobiles.

0 votes

Laissez-moi deviner : ce n'est pas unique, quand vous avez plus de 2**32 objets dans la même JVM ? ;) Pouvez-vous m'indiquer un endroit où la non-unicité est décrite ? Je vous remercie.

11 votes

Le nombre d'objets ou la quantité de mémoire disponible n'ont pas d'importance. Ni hashCode() ni identityHashCode() ne sont nécessaires pour produire un numéro unique.

12 votes

Brian : Il ne s'agit pas de l'emplacement réel de la mémoire, mais d'une version remaniée d'une adresse lors de son calcul initial. Dans une VM moderne, les objets se déplacent dans la mémoire.

29voto

Valentin Rocher Points 7524

La javadoc pour Object spécifie que

Cela se fait généralement en convertissant l'adresse interne de l'objet en un nombre entier, mais cette technique de mise en œuvre n'est pas requise par le langage de programmation JavaTM.

Si une classe surcharge hashCode, cela signifie qu'elle souhaite générer un identifiant spécifique, qui aura (on peut l'espérer) le bon comportement.

Vous pouvez utiliser System.identityHashCode pour obtenir cet identifiant pour n'importe quelle classe.

11voto

ovunccetin Points 1230

hashCode() n'est pas destinée à fournir un identifiant unique pour un objet. Elle digère plutôt l'état de l'objet (c'est-à-dire les valeurs des champs membres) en un seul entier. Cette valeur est principalement utilisée par certaines structures de données basées sur le hachage, telles que les cartes et les ensembles, pour stocker et récupérer efficacement les objets.

Si vous avez besoin d'un identifiant pour vos objets, je vous recommande d'ajouter votre propre méthode au lieu de surcharger la méthode hashCode . À cette fin, vous pouvez créer une interface de base (ou une classe abstraite) comme ci-dessous.

public interface IdentifiedObject<I> {
    I getId();
}

Exemple d'utilisation :

public class User implements IdentifiedObject<Integer> {
    private Integer studentId;

    public User(Integer studentId) {
        this.studentId = studentId;
    }

    @Override
    public Integer getId() {
        return studentId;
    }
}

7voto

chiwai Points 11

Peut-être que cette solution rapide et sale fonctionnera ?

public class A {
    static int UNIQUE_ID = 0;
    int uid = ++UNIQUE_ID;

    public int hashCode() {
        return uid;
    }
}

Cela donne également le nombre d'instances d'une classe en cours d'initialisation.

7voto

Frankie Points 12557
// looking for that last hex?
org.joda.DateTime@57110da6

Si vous vous intéressez à la hashcode Les types Java lorsque vous effectuez un .toString() sur un objet, le code sous-jacent est le suivant :

Integer.toHexString(hashCode())

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