[JAXB] nutzt Standard Konstruktor nicht?

Objektorientierte Programmiersprache auf Basis einer virtuellen Maschine (https://www.oracle.com/java/)
Zenerid
Beiträge: 38
Registriert: Do Feb 05, 2015 4:15 pm

[JAXB] nutzt Standard Konstruktor nicht?

Beitrag von Zenerid » Sa Okt 24, 2015 11:16 pm

Ich habe aktuelle ein kleines Problem mit der JAXB API, da ich grade versuche, meine Daten in einer XML Datei zu speichern bzw. diese dort auszulesen und aktuell geht es primär um das einlesen. Meine XML Datei sieht so aus:

Code: Alles auswählen

<?xml version="1.0"?>
<karte>
    <raueme>
        <raum id="1">
            <beschreibung>Der erste Raum</beschreibung>
            <nachbarn>
                <nachbar>
                    <richtung>geradeaus</richtung>
                    <ref>2</ref>
                </nachbar>
                <nachbar>
                    <richtung>rechts</richtung>
                    <ref>3</ref>
                </nachbar>
            <nachbarn>
        </raum>
        <raum id="2">
            <beschreibung>Raum 2</beschreibung>
            <nachbarn>
                <nachbar>
                    <richtung>zurück</richtung>
                    <ref>1</ref>
                </nachbar>
            <nachbarn>
        </raum>
        <raum id="3">
            <beschreibung>Der dritte Raum</beschreibung>
            <nachbarn>
                <nachbar>
                    <richtung>links</richtung>
                    <ref>1</ref>
                </nachbar>
            <nachbarn>
        </raum>
    </raueme>
</karte>
und so sieht der Raum aus:

Code: Alles auswählen

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "raum")@XmlAccessorType(XmlAccessType.NONE)
public class Raum
{    
    @XmlID
    @XmlAttribute
    private String id;

	private String beschreibung;
    
	@XmlElementWrapper(name = "nachbarn")@XmlElement(name = "nachbar")
    private Nachbar[] nachbarn;
    
    private static final int anzRichtungen = Richtung.values().length;
    
    public Raum() 
    {
        nachbarn = new Ausgang[anzahlRichtungen];
    }
    
    @XmlElement(name = "beschreibung")
    public void setBeschreibung(String beschreibung)
    {
        this.beschreibung = beschreibung;
    }
    
    public void setNachbar(Richtung richtung, Raum nachbar) 
    {
    	nachbarn[richtung.ordinal()] = new Nachbar(richtung, nachbar);
    }    

    public Nachbar getNachbar(Richtung richtung) 
    {
    	return nachbarn[richtung.ordinal()];
    }    
}  
Das Problem ist jetzt, das er irgendwie jeweils nur so viele Nachbarn in der Liste hat, wie ich in der XML Datei angebe aber da sollten doch laut dem Standardkonstruktor immer 4 Räume drin sein? Wieso ignoriert er dann einfach die Zeile, wo ich sage:

Code: Alles auswählen

nachbarn = new Ausgang[anzahlRichtungen];
Das sollten denn dann nämlich derzeit die Größe 4 (3) im Array sein aber für Raum 1 habe ich bspw. jetzt nur zwei Nachbarn. So habe ich nämlich jetzt auch das Problem, das er für alle Richtungen, außer geradeaus den falschen Raum (ref) als Nachbar zurückgibt. Wie kann ich das Problem also lösen, ohne das ich jetzt immer 4 Räume in der Datei angeben, also für jede Richtung angeben muss?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: [JAXB] nutzt Standard Konstruktor nicht?

Beitrag von Xin » Sa Okt 24, 2015 11:47 pm

Bei dem Quelltext verstehe ich einiges nicht.

Code: Alles auswählen

 private static final int anzRichtungen = Richtung.values().length;
    
    public Raum() 
    {
        nachbarn = new Ausgang[anzahlRichtungen];
    }
Wenn ich das richtig Verstehe, dann sollte er die Zeile nicht ignorieren, sondern nicht kompilieren.

Wenn das doch kompiliert, muss es irgendwo anders eine Variable anzahlRichtungen geben, die vielleicht nicht den Wert besitzt, den Du vermutest?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Zenerid
Beiträge: 38
Registriert: Do Feb 05, 2015 4:15 pm

Re: [JAXB] nutzt Standard Konstruktor nicht?

Beitrag von Zenerid » So Okt 25, 2015 12:31 am

Ja, das Programm kompiliert. Das habe ich grade nur noch kurz umgeschrieben, weil ich auch demnächst irgendwann auf Englisch umstellen will. Das ist aber sowieso nur Hobbymäßg, von daher spielt das eigentlich keine große Rolle. Die Variable anzRichtungen gibt es also nur einmal so und auch keine, mit ähnlichem Namen. Der Ausgang war auch falsch, denn die Klasse heißt jetzt Nachbar, da ich Ausgang irgendwie nicht passend fand.
Es sieht also derzeit so im Standard Konstruktor aus:

Code: Alles auswählen

nachbarn = new Nachbar[anzRichtungen];
Was verstehst du denn sonst nicht? Das mit dem ordinal oder was sonst nicht? Der Ordinal ist ja nur dafür da, damit immer der passende Raum für die entsprechende Richtung zurückgegeben wird. Die Enum Richtung sieht so aus:
GERADEAUS, RECHTS, LINKS; ZURÜCK
Also ist die erste Richtung Geradeaus usw.

Die Ausgangsklasse sieht so aus:

Code: Alles auswählen

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "nachbar")@XmlAccessorType(XmlAccessType.NONE)
public class Nachbar
{	
	 private Richtung richtung;
    private Raum nachbar;
    
    public Nachbar()
    {      

    }
    
    public Raum getNachbar()
    {
    	return this.nachbar;
    }
    
    public Richtung getRichtung()
    {
    	return this.richtung;
    }
    
    @XmlElement(name = "richtung")
    public void setRichtung(Richtung richtung)
    {
        this.richtung = richtung;
    }
    
    @XmlIDREF
    @XmlElement(name = "ref")
    public void setNachbar(Raum nachbar)
    {
        this.nachbar = (Raum) nachbar;
    }    
}
Klärt das jetzt alles auf? Tut mir Leid wegen dem Fehler oben mit der anzRichtungen und dem Nachbar (alt Ausgang) aber das kommt davon, wenn man noch hier und da was ändern will. :oops:

Was mir ja auch grad noch eingefallen ist, ist die Tatsache, das man ja auch vielleicht die SetNachbar Methode irgendwie benutzen könnte aber wie macht man das dann mit zwei Parametern. Wenn ich in Richtung x gehe, dann soll ja auch der passende Raum zurückgegeben werden. So wie ich das jetzt mache, wäre das ja nicht unbedingt sichergestellt oder?
Zuletzt geändert von Zenerid am So Okt 25, 2015 1:25 am, insgesamt 1-mal geändert.

nufan
Wiki-Moderator
Beiträge: 2557
Registriert: Sa Jul 05, 2008 3:21 pm

Re: [JAXB] nutzt Standard Konstruktor nicht?

Beitrag von nufan » So Okt 25, 2015 1:14 am

Ich finde, dass das Verhalten durchaus Sinn ergibt. Mit der Annotation über deinem Member "nachbarn" sagst du, dass JAXB die XML-Elemente behandeln soll. Um dies zu tun muss JAXB logischerweise zuerst ein Objekt anlegen, also den Konstruktor aufrufen. Das heißt du legst zwar zuerst 4 Nachbarn an, danach wird dein Array aber überschrieben. Prüf mal mit einer einfachen Ausgabe ob dein Konstruktor aufgerufen wird.
Soweit meine Vermutung auf den ersten Blick.

Zenerid
Beiträge: 38
Registriert: Do Feb 05, 2015 4:15 pm

Re: [JAXB] nutzt Standard Konstruktor nicht?

Beitrag von Zenerid » So Okt 25, 2015 1:27 am

Ja, wenn ich da was ausgebe, wie z.B Raum Konstruktor, dann kriege ich x-Mal die Ausgabe aber wie stelle ich das nun richtig, so das jeder Raum auch vier Nachbarn hat, auch wenn ein oder zwei sozusagen nicht vorhanden sind? Mir fällt da keine Möglichkeit ein. Ich habe meine letzte Nachricht hier auch noch ein wenig ergängz, vor ein paar Sekunden.

nufan
Wiki-Moderator
Beiträge: 2557
Registriert: Sa Jul 05, 2008 3:21 pm

Re: [JAXB] nutzt Standard Konstruktor nicht?

Beitrag von nufan » So Okt 25, 2015 1:54 am

Erklär mal bitte ganz genau was dein Programm überhaupt machen soll und was dein XML-Dokument darstellt.

Zenerid
Beiträge: 38
Registriert: Do Feb 05, 2015 4:15 pm

Re: [JAXB] nutzt Standard Konstruktor nicht?

Beitrag von Zenerid » So Okt 25, 2015 2:23 am

Das Programm ist in diesem Fall ein Spiel, was auch mit Eingaben arbeitet. Die XML Datei soll dann jeweils eine Karte darstellen oder ein komplettes Level, wie auch immer. Ein paar Sachen, wie z.B Gegenstände und was es sonst noch so gibt, habe ich mal der Übersichtlichkeit halber aus der XML Datei entfernt. Das tut ja aber auch da sowieso nichts zur Sache.

Aus der XML Datei wird dann ebend diese Karte geladen und das war's dann auch eigentlich schon.

nufan
Wiki-Moderator
Beiträge: 2557
Registriert: Sa Jul 05, 2008 3:21 pm

Re: [JAXB] nutzt Standard Konstruktor nicht?

Beitrag von nufan » So Okt 25, 2015 7:29 pm

Warum willst du dann 4 Räume speichern, obwohl du nur 2 hast?

Zenerid
Beiträge: 38
Registriert: Do Feb 05, 2015 4:15 pm

Re: [JAXB] nutzt Standard Konstruktor nicht?

Beitrag von Zenerid » So Okt 25, 2015 8:13 pm

Ich will ja nur ein Array der Größe 4 anlegen aber er legt ja dann immer ein Array von der Größe an, die ich auch in der XML Datei angegeben habe aber er soll ja ebend immer eines der Größe 4 anlegen. Ich will eines der Größe 4 anlegen, da ich ja auch 4 Richtungen derzeit habe und wenn ich das so mache, dann habe ich bei dem ersten Index ja immer direkt den passenden Raum dazu, also in dem Fall den Raum, der in der Richtung "geradeaus" liegt.

Wenn in einer Richtung kein Raum liegt, dann ist der index an der Stelle ja ebend null aber das ist ja egal.

nufan
Wiki-Moderator
Beiträge: 2557
Registriert: Sa Jul 05, 2008 3:21 pm

Re: [JAXB] nutzt Standard Konstruktor nicht?

Beitrag von nufan » So Okt 25, 2015 9:17 pm

Naja ich finde es relativ unschön Platz für Räume zu schaffen die nicht existieren aber egal. Ein ebenso unschöner Quickfix wäre wohl einfach prinzipiell für jede Richtung immer einen Raum im XML anzulegen und eine spezielle Referenz auf einen null-Raum anzugeben. Ich würde dir dazu raten nur existierende Räume einzulesen und jeweils die Richtung über das Objekt abzufragen. Du kannst sie dir dann ja in eine Map speichern, um direkt über die Richtung darauf zuzugreifen.

Antworten