Hallo zusammen,
ich habe kürzlich etwas entdeckt, das mich sehr verwundert hat. Dafür habe ich euch ein minimales, funktionierendes Beispiel geschrieben:
Was passiert:
- ein HashSet wird angelegt
- ein Objekt ("objektA") wird angelegt
- dem HashSet wird objektA hinzugefügt
- das HashSet und objektA werden in eine Datei serialisiert
- die Referenzen auf die Objekte werden aus dem Programm gelöscht
- das HashSet und objektA werden erneut geladen
- das HashSet bestätigt die Existenz von objektA in seinem Inhalt.
Eines vorweg: ich finde es gut, dass das funktioniert, es kommt meiner Anwendung entgegen. Aber: warum funktioniert das eigentlich? HashSets funktionieren ja auf Basis der "hashCode()"-Methode der Objekte, die sie speichern. Wenn ein Objekt seinen hashCode() ändert, so würde das HashSet das Objekt nicht mehr finden und ein Aufruf von "contains(...)" würde false zurückliefern.
Da der Aufruf von "contains(...)" aber true zurückliefert, lässt das nur einen Schluss zu: die Standard-Implementierung von "hashCode()" liefert über die Lebensdauer eines Objektes hinweg konstante Werte. Wenn man sich jetzt aber die API zu Object#hashCode() ansieht, so wird dort behauptet, dass die hashCode()-Implementierung auf der internen Objekt-ID basiert, die für jedes erzeugte Objekt einzigartig ist.
Und jetzt kommt die Stelle, wo ich mich frage, wieso der obige Code funktionieren kann: wenn ein Objekt serialisiert und erneut geladen wird, dann muss es zwangsläufig eine neue interne Objekt-ID bekommen (es könnte passieren, dass die ursprüngliche Objekt-ID schon vergeben ist). Daher müsste sich der hashCode() des Objektes ändern, da er ja auf eben jener ID passiert. Offensichtlich tut er das aber nicht, sonst würde das Objekt im HashSet nicht mehr gefunden werden. Die Ausgabe des Programms auf der Kommandozeile ist immer "This works".
Ein verzwicktes Rätsel - ich bin zwar froh, dass es funktioniert, aber ich wüsste gerne, warum es funktioniert. Kann jemand Licht auf diese Sache werfen?
Gruß,
Alan
ich habe kürzlich etwas entdeckt, das mich sehr verwundert hat. Dafür habe ich euch ein minimales, funktionierendes Beispiel geschrieben:
Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashSet;
public class SerializationTest {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
HashSet<MyObject> hashSet = new HashSet<MyObject>();
MyObject objectA = new MyObject();
hashSet.add(objectA);
// serialize to file
File file = new File("test");
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(hashSet);
oos.writeObject(objectA);
oos.close();
fos.close();
// set all references to null
hashSet = null;
objectA = null;
// reload from file
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
hashSet = (HashSet<MyObject>) ois.readObject();
objectA = (MyObject) ois.readObject();
// close the streams
ois.close();
fis.close();
file.delete();
// the critical call:
if (hashSet.contains(objectA)) {
System.out.println("This works");
// WHY does this work???
} else {
System.out.println("This does not work");
}
}
}
class MyObject implements Serializable {
public static final long serialVersionUID = 1L;
}
Was passiert:
- ein HashSet wird angelegt
- ein Objekt ("objektA") wird angelegt
- dem HashSet wird objektA hinzugefügt
- das HashSet und objektA werden in eine Datei serialisiert
- die Referenzen auf die Objekte werden aus dem Programm gelöscht
- das HashSet und objektA werden erneut geladen
- das HashSet bestätigt die Existenz von objektA in seinem Inhalt.
Eines vorweg: ich finde es gut, dass das funktioniert, es kommt meiner Anwendung entgegen. Aber: warum funktioniert das eigentlich? HashSets funktionieren ja auf Basis der "hashCode()"-Methode der Objekte, die sie speichern. Wenn ein Objekt seinen hashCode() ändert, so würde das HashSet das Objekt nicht mehr finden und ein Aufruf von "contains(...)" würde false zurückliefern.
Da der Aufruf von "contains(...)" aber true zurückliefert, lässt das nur einen Schluss zu: die Standard-Implementierung von "hashCode()" liefert über die Lebensdauer eines Objektes hinweg konstante Werte. Wenn man sich jetzt aber die API zu Object#hashCode() ansieht, so wird dort behauptet, dass die hashCode()-Implementierung auf der internen Objekt-ID basiert, die für jedes erzeugte Objekt einzigartig ist.
Und jetzt kommt die Stelle, wo ich mich frage, wieso der obige Code funktionieren kann: wenn ein Objekt serialisiert und erneut geladen wird, dann muss es zwangsläufig eine neue interne Objekt-ID bekommen (es könnte passieren, dass die ursprüngliche Objekt-ID schon vergeben ist). Daher müsste sich der hashCode() des Objektes ändern, da er ja auf eben jener ID passiert. Offensichtlich tut er das aber nicht, sonst würde das Objekt im HashSet nicht mehr gefunden werden. Die Ausgabe des Programms auf der Kommandozeile ist immer "This works".
Ein verzwicktes Rätsel - ich bin zwar froh, dass es funktioniert, aber ich wüsste gerne, warum es funktioniert. Kann jemand Licht auf diese Sache werfen?
Gruß,
Alan
Zuletzt bearbeitet: