Deserialisieren von unterschiedlichen Klasseninstanzen

cyrano

Mitglied
Hallo zusammen, ich tüftel jetzt schon eine ganze Weile an der folgenden Problematik und finde einfache keine Lösung:

Ich habe mehrere Instanzen verschiedener Klassen aus meinem Programm mit Simple serialisiert. In die Richtung macht es auch keinerlei Probleme. Auch die Deserialisierung läuft, wenn ich gezielt nur ein Objekt zurück hole, denn ich brauche bei Simple den Zugriff:

Java:
Klasse objekt = serialize.read(Klasse.class, file);

Ich habe aber die ganzen Dateien in einer File-Liste gespeichert und möchte sie beim Deserialisieren durchlaufen. Dabei weiß ich aber nicht, von welcher Klasse die Instanz ist. Allerdings ist das Wurzelelement der XML-Datei identisch mit dem Klassennamen. Also bräuchte ich eine Funktionalität, die so etwas wie:

Java:
obj = newInstanceOf("Klassenname");

Hat jemand eine Idee, wie man diese allgemeine Problematik lösen kann?

Viele Grüße und Danke im Voraus!
 

cyrano

Mitglied
Hallo Joose, ich glaube, ich sehe irgendwo vor lauter Bäumen, den Wald nicht mehr. Meine Dateien haben ja bestimmte Namen, aus denen ich sogar die Klasse ableiten könnte. Mir fehlt im Moment einfach der konkrete Weg, wie ich den String (entweder Dateiname oder Element im XML-File) nutzen kann, um daraus ein Objekt zu erzeugen. Der Weg, der ja einwandfrei funktioniert, ist:

Java:
//1. Objekt einlesen
Klasse1 obj1 = serialize.read(Klasse1.class, obj1file);
//2. Objekt einlesen
Klasse2 obj2 = serialize.read(Klasse2.class, obj2file);

Ich weiß nicht, ob das im ersten Post rüber kam. Ich könnte - über unterschiedliche Wege - ermitteln, welche Klasse als nächste erzeugt werden muss, aber wie kann ich das dem Programm mitteilen. Ich kann ja nicht einfach so etwas schreiben:

Java:
File.getName() obj = serialize.reade(File.getName().class, objFile);

:D

Deshalb hatte ich diese "imaginäre" obj = makeinstancof("Klassenanme")-Methode erfunden.
VG
 

cyrano

Mitglied
Dazu noch eine Info, die aus meinen bisherigen Ausführungen wohl nicht klar geworden ist. Ich suche nach einer automatisierten Möglichkeit, die unterschiedlichen Objekte anhand einer Liste zu öffnen. Natürlich könnte ich einfach eine if-Abfrage (oder ein switch verwenden), nach dem Motto:

Java:
if (file.getName().equals("class1.xml"))
{
Class1 obj = serialize.read....
}

if (file.getName().equals("class2.xml"))
{
Class2 obj = serialize.read.... 
}

Problem dabei ist nur, dass es sehr sehr viele unterschiedliche Objektklassen gibt und ich dann beim Erweitern jedes Mal den Code wieder ändern muss.
 

cyrano

Mitglied
Hallo,

also ich erzeuge unterschiedliche grafische Objekte und stelle sie auf dem Bildschirm dar. Es gibt eine abstrakte Basisklasse für die Attribute und Methoden, die alle Objekte benötigen. Ich arbeite übrigens mit JavaFX, aber mein Problem ist wohl auch auf alle anderen Frameworks übertragbar.

Bestimmte Anordnungen dieser Objekte werden dann gespeichert. Das funktioniert, weil ich eine Liste vom Typ <Basisklasse> habe, in der alle Objekte gespeichert werden.

Wenn ich nun eine alte Konfiguration laden möchte, muss ich ja die einzelnen Objekte wieder herstellen. Zunächst hatte ich alle Objekte in einer xml-Datei, dann habe ich für jedes Objekt eine Datei erzeugt. Aber das Problem ist ja das selbe: beim Erzeugen in der for-Schleife muss ich ja die Klasse angeben, also eine Anweisung, die eine variable Klasse enthält.

Ich hoffe, das ich das einigermaßen verständlich rüber gebracht habe.

Viele Grüße
 

cyrano

Mitglied
Hallo Joose,

es hat ein wenig länger gedauert, weil ich mich mit dem letzten Link erst einmal etwas genauer auseinander setzen musste. Vom Prinzip scheint das ja die Lösung zu sein, aber ich komme einfach nicht konkret weiter.

Wie im Link beschrieben habe ich zunächst einmal ein Klassenobjekt erzeugt:

Java:
Class<?> compClass = Class.forName("vollständiger.packagname.plus.klassenname");

Das klappt ja auch und ich erhalte ein Klassenobjekt. Allerdings ist mir noch nicht wirklich klar, wie ich damit weiter mache. Zunächst habe ich mal folgendes probiert:

Java:
Basisklasse objekt1 = serialize.read(compClass, xmlFile);

Damit erhalte ich aber die Fehlermeldung, dass die Typen Object und Basisklasse nicht kompatibel sind. Dann habe ich versucht, eine neue Instanz der Klasse zu erzeugen und zwar mit:

Java:
Basisklasse objekt1 = compClass.newInstance();

Naiverweise hatte ich gedacht, dass ich damit eine Instanz von "klassenname" erzeuge. Aber es bleibt ein Object. In einem weiteren Link habe ich noch gelesen, dass man das Objekt dann noch casten muss, aber das wäre für mich unverständlich, wenn ich erst ein Klassenobjekt speziell für diese Klasse erzeuge. Außerdem, wenn ich es casten könnte, hätte ich ja das ganze Problem nicht :eek:((

Hast Du (oder jemand anders) eine Idee wo mein Denkfehler ist??
 

cyrano

Mitglied
Ein kleines bisschen bin ich noch weiter gekommen. Und zwar habe ich mir mal im Debugger angeschaut, mit welchen Objekten ich es zu tun habe. Also nach dem oben aufgeführten Code, der sich ein Klassenobjekt holt und dann eine neue Instanz erzeugt, habe ich tatsächlich eine Instanz der gewünschten Klasse. Allerdings habe ich noch ein kleines Problem, das aber auch meine obige Frage beantwortet, warum ich das Objekt noch explizit casten muss. Das Ganze geschieht ja zur Laufzeit. Bei der Programmerstellung weiß der Compiler ja noch nicht, von welcher Klasse sich die Instanz bildet.

Aber da wäre ich auch bei meinem nächsten Problem: Wie kann ich ein dynamisches Casting durchführen?

Es gibt ja die Methode:

Java:
obj = compClass.cast(objekt1);

Aber damit komme ich ja auch nicht weiter, weil das Casting wieder zur Laufzeit passiert und somit unsinnig wäre, weil dann eben kein Casting mehr notwendig ist.

So langsam raucht mir das Hirn :confused:... irgendwo hakt es immer an einer Stelle...
 

Joose

Top Contributor
Hier eine Methode für den Cast:

Java:
public <T> T castObject(Object o, Class<T> clazz) {
    return (T)o;
}

Basisklasse objekt = castObject(deinObject, SpezifischeKlasse1.class);

Sollte glaube ich so passen. Die IDE wird dich vor ungeprüften Casts warnen -> also ein entsprechendes Fehlerhandling müsstet du dann noch einbauen.
 

cyrano

Mitglied
Hallo Joose, sorry, das ich so lange nicht geantwortet habe. Deinen Ansatz werde ich jetzt erst einmal ausprobieren, vorher aber noch ein wenig tiefer einsteigen. Mir fehlen noch die entsprechenden Grundlagen, um das wirklich nachvollziehen zu können. Danke für Deine Hilfe!
 

cyrano

Mitglied
Da bin ich noch einmal. Weil doch eine ganze Menge Leute diesen Post verfolgen, möchte ich kurz darstellen, wie ich es jetzt lösen konnte. Es geht viel einfacher als ich dachte, soll aber nicht heißen, dass die Lösung von Joose kompliziert ist. Das ist mit Sicherheit der optimale Weg, wenn man nicht mit "Simple" serialisiert. Doch das Framework bietet wirklich einiges.

Wenn man mehrere unterschiedliche Objekte serialisieren möchte, dann nimmt man sich die Klasse, die am besten als Basisklasse passt. Bei mir war das eine eigene Klasse, die "BasicComponent" heißt. Um die ganze Collection zu speichern habe ich eine Klasse erstellt, z. B. Configuration in der sich eine Liste vom Typ BasicComponent befindet.

Wenn ich meine Konfiguration speichern möchte, serialisiere ich ganz einfach dieses Objekt, mit:

Java:
serialize.write(Configuration.class, dateiname);

Dadurch erhalte ich ein xml-File, in dem alle Variablen der Basisklasse und deren aktuelle Inhalte gespeichert werden, zuzüglich der speziellen Variablen, die ich in den abgeleiteten Klassen mit der Annotation @ Element versehen habe. Außerdem wird der Klassentyp als Attribut gespeichert.

Beim Deserialisieren läuft das Ganze anders herum. Ich erzeuge eine Instanz von Configuration und rufe den Deserialisierer auf:

Java:
Configuration configuration = serialize.read(Configuration.class, Dateiname);

Jetzt steht mir die alte Objektliste wieder zur Verfügung und ich kann alle meine Objekte mit:

Java:
screen.getChildren().addAll(configuration.getCompList());

wieder auf den Bildschirm holen. Ich muss natürlich dazu sagen, dass meine Klasse BasicCompoenten vom Typ "VBox" ist und damit darstellbar. Ein Casting auf die abgeleiteten Klassen ist nicht nötig, weil Simple das beim Deserialisieren automatisch macht.

Wer sich Simple mal genauer anschauen möchte, hier ist der Link für den Download und Tutorials gibt es dort auch:
http://simple.sourceforge.net/
 

Joose

Top Contributor
Kannst du dann auch nur spezifische Elemente laden und speichern? Das wäre ein möglicher Nachteil der mir einfallen würde.

Wenn du nur ein bestimmtes Objekt laden willst und dafür aber alles laden müsstest.
 

cyrano

Mitglied
Ich weiß nicht genau, ob es in Simple eine spezielle Funktion dazu gibt, so genau kenne ich das Framework noch nicht. Allerdings gibt es nur die Methode "serialize.read()" und hier finde ich keine Parameter, die so etwas zuließen. Allerdings kannst Du natürlich an beliebigen Stellen des Programms auch nur gezielte Zustände der Liste oder auch einzelne Objekte serialisieren. Die Auswahl wäre dann auf der "Serialisierungsseite" zu treffen.

Auf die von Simple erstellte xml-Datei kann natürlich auch z. B. über jdom zugegriffen werden. Nur damit hätte ich persönlich bei meiner Aufgabenstellung dann wieder das Problem, die typrichtige Herstellung der Instanz zu realisieren.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
F Gson deserialisieren mit PropertyChangeSupport Allgemeine Java-Themen 4
M Objekt serialisieren/deserialisieren und in einer SQLite-Datenbank speichern Allgemeine Java-Themen 3
F Schlüsselworte Einstellungen dynamisch deserialisieren Allgemeine Java-Themen 5
T Objekt 2x deserialisieren, aber nur 1x im Heap haben? Allgemeine Java-Themen 4
X Objekte aus TableModel serialisieren und deserialisieren Allgemeine Java-Themen 4
A Problem beim serialisieren/deserialisieren einer ArrayList Allgemeine Java-Themen 3
S Deserialisieren mit anderem Klassennamen Allgemeine Java-Themen 5
G Direkt in ein Objekt deserialisieren Allgemeine Java-Themen 5
B Nach Deserialisieren: Elemente des JFrames ohne Funktion Allgemeine Java-Themen 5
P Servlet, Deserialisieren, StreamCorruptedException Allgemeine Java-Themen 9
Tarrew OpenAPI Schnittstelle - Mehrere Kunden mit unterschiedlichen Zugriffsrechten Allgemeine Java-Themen 2
E Datentypen Wie kann ich die Längen der unterschiedlichen Ebenen aus einem Objekt lesen von dem ich weiß, dass es ein mehrdimensionaler Array ist? Allgemeine Java-Themen 3
J Best Practice Umgang mit unterschiedlichen Tasks Allgemeine Java-Themen 2
M 2D Array mit unterschiedlichen Längen erstellen und befüllen Allgemeine Java-Themen 11
Z Array mit unterschiedlichen Werten Allgemeine Java-Themen 1
S Probleme mit unterschiedlichen Java-Versionen (Mac OS X 10.11) Allgemeine Java-Themen 0
Viktim Threads Liste In unterschiedlichen Threads bearbeiten Allgemeine Java-Themen 23
Y inhalte aus 2 unterschiedlichen Arrays miteinander vergleichen Allgemeine Java-Themen 12
D Problem mit unterschiedlichen FontMetrics Allgemeine Java-Themen 1
K JNI: Methoden aus unterschiedlichen Threads aufrufen Allgemeine Java-Themen 3
Gossi Threads mit unterschiedlichen Aufgaben in einer Klasse? Allgemeine Java-Themen 9
J Jars in unterschiedlichen Versionen Allgemeine Java-Themen 14
C Kombinationen von ArrayListen mit unterschiedlichen Längen Allgemeine Java-Themen 7
A Unterschiedlicher Objektgebrauch in unterschiedlichen ActionListenern Allgemeine Java-Themen 7
H2SO3- csv Datei mit unterschiedlichen Formatierungen einlesen Allgemeine Java-Themen 15
A Probleme mit der unterschiedlichen Bildschirmeinstellungen Allgemeine Java-Themen 4
S Methoden aus Interfaces mit unterschiedlichen Parametertypen Allgemeine Java-Themen 7
xYurisha Nutzen von Importmethoden bei Klasseninstanzen Allgemeine Java-Themen 12

Ähnliche Java Themen

Neue Themen


Oben