Wenn eine Klasse in Java hashCode () nicht überschreibt , ergibt das Drucken einer Instanz dieser Klasse eine schöne eindeutige Nummer.
Das Javadoc von Object sagt über hashCode () :
Soweit dies vernünftigerweise praktikabel ist, gibt die von class Object definierte hashCode-Methode unterschiedliche Ganzzahlen für unterschiedliche Objekte zurück.
Aber wenn die Klasse hashCode () überschreibt , wie kann ich ihre eindeutige Nummer erhalten?
Antworten:
System.identityHashCode (yourObject) gibt den 'ursprünglichen' Hash-Code IhresObjects als Ganzzahl an. Einzigartigkeit ist nicht unbedingt garantiert. Die Sun JVM-Implementierung gibt Ihnen einen Wert, der sich auf die ursprüngliche Speicheradresse für dieses Objekt bezieht. Dies ist jedoch ein Implementierungsdetail, auf das Sie sich nicht verlassen sollten.
BEARBEITEN: Antwort geändert nach Toms Kommentar unten bezüglich. Speicheradressen und sich bewegende Objekte.
quelle
System.identityHashCode()
?Das Javadoc für Object gibt dies an
Wenn eine Klasse hashCode überschreibt, bedeutet dies, dass sie eine bestimmte ID generieren möchte, die (man kann hoffen) das richtige Verhalten hat.
Sie können System.identityHashCode verwenden , um diese ID für jede Klasse abzurufen .
quelle
Vielleicht funktioniert diese schnelle, schmutzige Lösung?
Dies gibt auch die Anzahl der Instanzen einer Klasse an, die initialisiert werden.
quelle
System.identityHashCode
ist eine bessere LösungAtomicLong
wie in dieser Antwort verwenden .hashCode()
Die Methode dient nicht zur Bereitstellung einer eindeutigen Kennung für ein Objekt. Vielmehr wird der Status des Objekts (dh die Werte der Mitgliedsfelder) in eine einzelne Ganzzahl umgewandelt. Dieser Wert wird hauptsächlich von einigen Hash-basierten Datenstrukturen wie Karten und Sets verwendet, um Objekte effektiv zu speichern und abzurufen.Wenn Sie eine Kennung für Ihre Objekte benötigen, empfehle ich Ihnen, eine eigene Methode hinzuzufügen, anstatt diese zu überschreiben
hashCode
. Zu diesem Zweck können Sie eine Basisschnittstelle (oder eine abstrakte Klasse) wie unten erstellen.Anwendungsbeispiel:
quelle
Wenn es sich um eine Klasse handelt, die Sie ändern können, können Sie eine Klassenvariable deklarieren
static java.util.concurrent.atomic.AtomicInteger nextInstanceId
. (Sie müssen ihm auf offensichtliche Weise einen Anfangswert geben.) Deklarieren Sie dann eine Instanzvariableint instanceId = nextInstanceId.getAndIncrement()
.quelle
Ich habe diese Lösung entwickelt, die in meinem Fall funktioniert, wenn ich Objekte auf mehreren Threads erstellt habe und serialisierbar bin:
quelle
Wenn Sie sich mit den
hashcode
Java-Typen befassen, während Sie.toString()
ein Objekt ausführen, lautet der zugrunde liegende Code wie folgt:quelle
Nur um die anderen Antworten aus einem anderen Blickwinkel zu erweitern.
Wenn Sie Hashcodes von 'oben' wiederverwenden und neue Codes unter Verwendung des unveränderlichen Status Ihrer Klasse ableiten möchten, funktioniert ein Aufruf von super. Dies kann / kann nicht bis zum Objekt kaskadieren (dh einige Vorfahren nennen Super möglicherweise nicht), ermöglicht es Ihnen jedoch, Hashcodes durch Wiederverwendung abzuleiten.
quelle
Es gibt einen Unterschied zwischen hashCode () und identityHashCode (). Es ist möglich, dass für zwei ungleiche (mit == getestete) Objekte o1, o2 hashCode () gleich sein kann. Sehen Sie sich das folgende Beispiel an, wie dies wahr ist.
quelle
Ich hatte das gleiche Problem und war bisher mit keiner der Antworten zufrieden, da keine von ihnen eindeutige IDs garantierte.
Ich wollte auch Objekt-IDs zum Debuggen drucken. Ich wusste, dass es eine Möglichkeit geben muss, dies zu tun, da im Eclipse-Debugger eindeutige IDs für jedes Objekt angegeben werden.
Ich habe eine Lösung gefunden, die darauf basiert, dass der Operator "==" für Objekte nur dann true zurückgibt, wenn die beiden Objekte tatsächlich dieselbe Instanz sind.
Ich glaube, dass dies eindeutige IDs während der gesamten Laufzeit des Programms sicherstellen sollte. Beachten Sie jedoch, dass Sie dies wahrscheinlich nicht in einer Produktionsanwendung verwenden möchten, da Verweise auf alle Objekte beibehalten werden, für die Sie IDs generieren. Dies bedeutet, dass Objekte, für die Sie eine ID erstellen, niemals mit Müll gesammelt werden.
Da ich dies für Debug-Zwecke verwende, bin ich nicht allzu besorgt darüber, dass Speicher freigegeben wird.
Sie können dies ändern, um das Löschen von Objekten oder das Entfernen einzelner Objekte zu ermöglichen, wenn das Freigeben von Speicher ein Problem darstellt.
quelle