Problem mit Singleton bzw statischer Referenz!

Luk10

Top Contributor
Hallo,

Ich habe eine Klasse die einen großteil meines Programms verwaltet und ich keine 2. Instanz dieser Klasse will! Deswegen wollte ich mal das singelton-muster ausprobieren!

Leider stößt das auf enorme Probleme.
Ich brauche in dieser Klasse referenzen auf andere Instanzen, anderer Klassen, sowie instanzvariablen ...

Wie kann ich mein Problem am besten lösen?
Hier mal ein Beispiele:

Java:
public class Verwalter {
  private int gitterG;
  
  private static Verwalter walter;

  private final String PATH_PFLANZE = "";
  private final String PATH_FRESS = "";
  Zellfabrik fabrik;
  Uploader load;
  GamePanel panel;
  
  ArrayList<Grafiken> alleGrafiken;
  
  private Verwalter () {
      gitterG = 20;
      alleGrafiken = new ArrayList<Grafiken>();
      fabrik = new Zellfabrik();
      load = new Uploader();
    }
    
    public void createCell (int i) {
        alleGrafiken.add(fabrik.getZelle(i));
    }
    public Image holImage (int i) {
        if (i == 1) {
            return load.getImage(PATH_PFLANZE);
        }
        if (i == 2) {
            return load.getImage(PATH_FRESS);
        }
        else {
            return null;
        }
    }
    public static Verwalter getWalter () {
        if (walter == null) {
            walter = new Verwalter();
        }
        return walter;
    }
    public int getGitterGroesse () {
        return gitterG;
    }
}
 
Zuletzt bearbeitet:
dass Verwalter eine Zellfabrik braucht und daher ein Klassenattribut hat und vielleicht selber ein entsprechendes Objekt anlegt mag so sein oder auch nicht,
das ist keine Problembeschreibung und allgemein auch nicht weiter bedenklich/ ungewöhlich,
jedenfalls nicht schlimmer als überhaupt ein Singleton zu haben
 
Ich bekomme aber Massive Exceptions wohin ich auch schaue ...

Ich dachte es liegt am Singelton und jemand wüsste mir zu helfen bzw. meine Fehler aufzuzeigen
 
Die finalen Strings sind Datenpfade, welche ich noch nicht sicher belegen kann, deshalb vorerst leer!

java.lang.StackOverflowError
at java.util.ArrayList.<init>(ArrayList.java:119)
at Verwalter.<init>(Verwalter.java:19)
at Verwalter.getWalter(Verwalter.java:49)
at Zellfabrik.<init>(Zellfabrik.java:4)
at Verwalter.<init>(Verwalter.java:20)
at Verwalter.getWalter(Verwalter.java:49)


Das geht noch ewig so weiter ...
 
Ich hab ein bisschen rumprobiert, weiß jetzt wo das Problem ist jedoch nicht was an meinem Code falsch sein soll:

Java:
public class Zellfabrik {
  Verwalter walter;
  public Zellfabrik () {
      walter = Verwalter.getWalter ();
    }
    public Zelle getZelle (int typ) {
        if (typ == 1) {
            return new Pflanzenzelle(walter.getX(), walter.getY(), walter.holImage(1));
        }
        if (typ == 2) {
            return new Fresszelle(walter.getX(), walter.getY(), walter.holImage(2));
        }
        else {
            return null;
        }
    }
}

Das ist die Zellfabrik, welche maßgeblich an der Exception schuld ist!
Wenn ich die Methode getZelle in Verwalter lege und die Klasse lösch funktioniert alles problemlos!

:noe:
 
schreibe
Java:
 public static Verwalter getWalter () {
        if (walter == null) {
            walter = new Verwalter();
            walter.init();
        }
        return walter;
    }
alles aus dem Verwalter-Konstruktor kommt in die init-Methode, dann kann in Zellfabrik.<init> & Co schon auf das statisch Verwalter-Singleton-Objekt zugegriffen werden,
allerdings evtl. noch nicht voll initialisiert, also auf bisschen Reihenfolge muss man schon achten

alternativ den Verwalter als Parameter an den Konstruktor von Zellfabrik & Co. übergeben, was aber auch noch nicht denkbaren Abhängigkeiten löst,
z.B.: wenn im Verwalter-Konstruktor der Zellfabrik-Konstruktor aufgerufen wird und Zellfabrik dann wieder auf Verwalter zugreift, ist Uploader noch null, denn Uploader wird erst nach fertiger Zellfabrik angelegt
 
Die finalen Strings sind Datenpfade, welche ich noch nicht sicher belegen kann, deshalb vorerst leer!
Wenn sie final sind dann ist voreerst == für immer

Code:
java.lang.StackOverflowError
	at java.util.ArrayList.<init>(ArrayList.java:119)
	at Verwalter.<init>(Verwalter.java:19)
	at Verwalter.getWalter(Verwalter.java:49)
	at Zellfabrik.<init>(Zellfabrik.java:4)
	at Verwalter.<init>(Verwalter.java:20)
	at Verwalter.getWalter(Verwalter.java:49)
Fällt dir da etwas auf? 😉
Der Konstruktor von Verwalter ruft den Konstruktor von ZellFabrik auf, welcher wieder den Konstruktor von Verwalter aufruft... eine Endlosschleife, wie meistens bei StackOverflowExceptions.

Mach dir erstmal Gedanken darüber welches Objekt von welchem Abhängig ist bzw. sein darf.

Nachtrag: SlaterB war mal wieder schneller 😀
 
Wenn sie final sind dann ist voreerst == für immer

Das Programm ist noch nicht annäherd fertig und mitten in der Erstellungsphase!
Ich werde den Pfad und das Image erst noch anlegen ...


SlaterB hat gesagt.:
evtl. noch nicht voll initialisiert, also auf bisschen Reihenfolge muss man schon achten

Was meinst du mit "noch nicht voll initialisieren"?
Könnte ich das Problem nicht mit einer vorgezogenen Initialisierung machen (Hab ich mal gelesen im zumsammenhang mit Multithreading):

Java:
private static Verwalter walter = new Verwalter();

Oder ginge da der Singleton-Effekt verloren?
 
> Was meinst du mit "noch nicht voll initialisieren"?

das was ich bei 'z.B.' schrieb

> Könnte ich das Problem nicht mit einer vorgezogenen Initialisierung machen

der Grund für die Endlosreferenz sollte nun klar sein, wie man es löst muss man sich überlegen,
das hat nichts mit Singleton, static oder sonst einem Grundprinzip zu tun, sondern nur mit Reihenfolge,
Henne-Ei-Problem
 
Das wird aber bestimmt ein sehr lustiges Programm, wenn ein einziger Verwalter mit Zell(stoff)fabriken, Uploadern, GamePaneln, Pflanzen- und Fress-Strings korrespondieren muss?! 😀

Wie kann eigentlich ein Uplader dazubeitragen, das ein Bild geholt wird?
Java:
public Image holImage (int i) {
        if (i == 1) {
            return load.getImage(PATH_PFLANZE);
        }
       ...

Warum übergibst du bei holImage(Denglish i) eigentlich ein integer? Woher soll denn ein anderer Entwickler wissen, welche Zahlen er da übergeben kann? Ein Enum oder ein paar öffentliche Konstanten wären da sehr angebracht!

Entscheide dich mal für Englisch oder Deutsch im Quelltext!

Und ob ein Walter gleich einem Verwalter ist, kann man sich auch streiten.

Java:
private final String PATH_PFLANZE = "";
private final String PATH_FRESS = "";
Die beiden Konstanten sollten auch als static deklariert werden.

Und 'gitterG' solltest du in 'groesse' oder 'size' umbenennen!

Naja, hat zwar nicht viel mit deinem Problem zu tun gehabt, aber es waren halt in deinem Quelltext viele Schönheitsfehler drin.
 
Hm da magst du recht haben, aber ich schreibe diese Programm für mich und für keinen anderen Entwickler welcher meinen Code verstehen soll ...
Ich experementiere gerade mit Desing-patterns, deshalb mag die Struktur etwas zu wünschen übrig lassen ...

Ausserdem tut das meinem Problem wirklich nichts (bzw. nicht maßgeblich) zur Sache!
Bei solche Sachen wäre meiner Meinung nach eine private Nachricht angebrachter ... (Bin gere für solche Kritik offen)

Luk :rtfm:
 
In dem Moment wo du deinen Code hier im Forum veröffentlichst (wie im ersten Post) ist es aber schon für "andere Entwickler" 😛
 
agentone hat Recht mit dem was er sagt, es ist vollkommen egal für wen du das Programm schreibst, sauberer & strukturierter Quellcode bietet viel weniger Platz für Bugs als unsauberer & unstrukturierter Quellcode.
Da du dich offensichtlich in deinem eigenem Code nicht mehr auskennst solltest du seinem Rat folgen und dir die Ausreden sparen 😉
 

Zurück
Oben