[Java] NullPointer bij Singleton

Pagina: 1
Acties:
  • 391 views sinds 30-01-2008
  • Reageer

  • 2playgames
  • Registratie: Februari 2005
  • Laatst online: 01-06 15:19
ik heb een singleton klasse gemaakt (het voorbeeld heb ik van Wikipedia):
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class MainApp {

    public MainWindow mainWindow;
    public ControlStreamReader socketReader;

    /**
     * Start de applicatie
     * @param args De commandline argumenten. Voor deze applicatie niet van toepassing
     */
    public static void main(String[] args) {
        MainApp.get();
    }

    /**
     * Verkrijg de hoofdklasse van de applicatie
     * Hij wordt gemaakt als hij nog niet bestaat
     */
    public static MainApp get() {
        return SingletonHolder.instance;
    }
    private static class SingletonHolder {
        private static MainApp instance = new MainApp();
    }
    
    // private constructor volgens het Singleton principe
    private MainApp() {
        mainWindow = new MainWindow();
    }

}


de eerste aanroep van get() in main() gaat goed, en het programma start normaal. als ik dan later in een andere klass MainApp.get().methode() aanroep, krijg ik een de volgende error voor mn kiezen:
Exception in thread "main" java.lang.ExceptionInInitializerError
at ica.elo.MainApp.get(MainApp.java:31)
at ica.elo.MainApp.main(MainApp.java:23)
Caused by: java.lang.NullPointerException
at ica.elo.MainWindow.showConnectDialog(MainWindow.java:129)
at ica.elo.MainWindow.access$0(MainWindow.java:124)
at ica.elo.MainWindow$1.widgetSelected(MainWindow.java:65)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:227)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:66)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:938)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3673)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3284)
at ica.elo.MainWindow.<init>(MainWindow.java:39)
at ica.elo.MainApp.<init>(MainApp.java:39)
at ica.elo.MainApp.<init>(MainApp.java:38)
at ica.elo.MainApp$SingletonHolder.<clinit>(MainApp.java:34)
... 2 more
regel 129 van MainWindow.java bevat dus "MainApp.get().methode();"

wat kan ik aan dit supersimpele principe nou fout hebben gedaan dat het niet werkt? :(

bij voorbaat dank _/-\o_

edit: ik heb eerst ook nog dit geprobeerd, maar kreeg toen ook een nullpointerfout
Java:
1
2
3
4
5
6
7
8
9
10
11
12
public class MainApp {

private static MainApp instance = null;

public static MainApp get() {
    if(instance == null) instance = new MainApp();
    return instance;
}

// ... constructor en de rest

}

[ Voor 6% gewijzigd door 2playgames op 09-05-2007 18:51 ]


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 05-11 19:33
Compile en probeer dit eens:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Test
{
    public static void main(String[] args)
    {
        getInstance().printHello();
    }

    private static Test instance;

    public static Test getInstance()
    {
        if ( instance == null )
        {
            instance = new Test();
        }
        return instance;
    }

    public void printHello()
    {
        System.out.println("Hello");
    }
}

Hier werkt het iig.

Noushka's Magnificent Dream | Unity


  • NetForce1
  • Registratie: November 2001
  • Laatst online: 23:17

NetForce1

(inspiratie == 0) -> true

Misschien komt het omdat de constructor van MainWindow er voor zorgt dat een event gefired wordt, vervolgens probjeer je in je event handler aan de singleton instance te refereren. Die is echter nog niet geset omdat de constructor nog bezig is. Je tweede probeersel brengt me echter aan het twijfelen over deze theorie, ik had hier nl een stack overflow verwacht dan.

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • 2playgames
  • Registratie: Februari 2005
  • Laatst online: 01-06 15:19
@Michali: ja dat werkt
@NetForce1: de tweede get() wordt pas aangeroepen nadat de applicatie is gestart en ik een dialoogvenster heb laten zien en ingevuld, dus de constructor is dan al klaar

edit: ik heb het gevonden. het lijkt een beetje op de suggestie van NetForce1. wat er gebeurt is dat in MainApp() een nieuwe MainWindow gemaakt wordt. in deze constructor wordt een SWT Shell gemaakt en daarna komt de eventloop (die niet afloopt tot het programma gesloten wordt). ik ga het oplossen door deze code dus buiten de constructors te halen.

[ Voor 48% gewijzigd door 2playgames op 09-05-2007 19:37 ]


  • NetForce1
  • Registratie: November 2001
  • Laatst online: 23:17

NetForce1

(inspiratie == 0) -> true

Dan is op de een of andere wazige fiets je klasse verdwenen uit de classloader, anders kan ie nooit die static init nog een keer uit gaan voeren

[ Voor 4% gewijzigd door NetForce1 op 09-05-2007 19:38 ]

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • 2playgames
  • Registratie: Februari 2005
  • Laatst online: 01-06 15:19
zie edit in vorige post :)

  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

Mag ik vragen waarom je een uitvoerbare Java Applicatie als een singleton wil ontwerpen? Wellicht zijn er veel betere oplossingen ;)

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 30-11 11:20

voodooless

Sound is no voodoo!

code:
1
2
Caused by: java.lang.NullPointerException
at ica.elo.MainWindow.showConnectDialog(MainWindow.java:129)


Daar zit dus de fout, regel 129 van MainWindow.

Do diamonds shine on the dark side of the moon :?


  • dawuss
  • Registratie: Maart 2001
  • Laatst online: 24-11 12:28

dawuss

gadgeteer

voodooless schreef op woensdag 09 mei 2007 @ 21:28:
code:
1
2
Caused by: java.lang.NullPointerException
at ica.elo.MainWindow.showConnectDialog(MainWindow.java:129)


Daar zit dus de fout, regel 129 van MainWindow.
Niet zo gek natuurlijk, daar probeert hij een methode aan te roepen op de singleton-class:
Java:
1
MainApp.get().methode()


Dit kan voorkomen omdat je (in mijn ogen) een gammele implementatie van het Singleton pattern hebt geschreven: wat de get() methode teruggeeft is tenslotte afhankelijk van het al dan niet eerder geïnstantieerd zijn van de klasse MainApp. Wat in je commentaar staat en wat je klasse daadwerkelijk doet is niet hetzelfde.

Je roept deze nota bene zelf verkeerd aan in de static main(): daar weet je absoluut zeker dat die MainApp.get() null teruggeeft!

Probeer het zo eens:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class MainApp { 

    private MainWindow mainWindow; // private (good coding practice)
    private ControlStreamReader socketReader; // private (good coding practice)

    private static MainApp mainApp; // this is the Singleton instance!

    /** 
     * Start de applicatie 
     * @param args De commandline argumenten. Voor deze applicatie niet van toepassing 
     */ 
    public static void main(String[] args) { 
        System.out.println(MainApp.get()); 
    } 

    /** 
     * Verkrijg de hoofdklasse van de applicatie 
     * Hij wordt gemaakt als hij nog niet bestaat 
     * @ensure instanceOf(MainApp.get()) == MainApp && MainApp.get() != null
     */ 
    public static MainApp get() { 
        if(mainApp == null) {
            mainApp = new MainApp();
        }

        return mainApp;
    } 
    
    // private constructor volgens het Singleton principe 
    private MainApp() { 
        mainWindow = new MainWindow(); 
    } 

     // getters (evt ook setters)
    public MainWindow getMainWindow() {
        return this.mainWindow;
    }

    public ControlStreamReader getSocketReader() {
        return this.socketReader;
    }

}

[ Voor 53% gewijzigd door dawuss op 09-05-2007 22:07 . Reden: oplossing erbij ]

micheljansen.org
Fulltime Verslaafde Commandline Fetisjist ©


  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 30-11 11:20

voodooless

Sound is no voodoo!

Ah, ik zie het ja. Lekker recursief :+

Hmm, toch niet ;) Volgens mij gaat er gewoon wat mis op die regel en heeft dat verder niets met de singleton te maken.

En als je er niet uit komt, gooi het dan ff in de debugger :)

[ Voor 78% gewijzigd door voodooless op 09-05-2007 22:08 ]

Do diamonds shine on the dark side of the moon :?


  • dawuss
  • Registratie: Maart 2001
  • Laatst online: 24-11 12:28

dawuss

gadgeteer

voodooless schreef op woensdag 09 mei 2007 @ 21:59:
Ah, ik zie het ja. Lekker recursief :+

Hmm, toch niet ;) Volgens mij gaat er gewoon wat mis op die regel en heeft dat verder niets met de singleton te maken.
Nee, het probleem is gewoon dat MainWindow.get() null kan opleveren, ik vermoed omdat de SingletonHolder private is (maar ik vind dat ook maar een slecht leesbare constructie).

micheljansen.org
Fulltime Verslaafde Commandline Fetisjist ©


  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 30-11 11:20

voodooless

Sound is no voodoo!

Dat kan alleen als de constructie van MainApp() faalt (dus java.lang.ExceptionInInitializerError). Er gaat dus wel degelijk wat mis in de de constructor van MainApp() (nullpointer @ regel 129).

Do diamonds shine on the dark side of the moon :?


  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

In plaats van om zijn singletonprobleem te oplossen kunnen we ook wachten op het antwoord waarom hij per-se een uitvoerbare java applicatie in een singleton wil gieten. Dat je specifieke utilityklassen als een singleton ontwerpt, oké, maar een uitvoerbare applicatie? Hier steekt meer 'bad design' achter :)

  • dawuss
  • Registratie: Maart 2001
  • Laatst online: 24-11 12:28

dawuss

gadgeteer

voodooless schreef op woensdag 09 mei 2007 @ 22:11:
Dat kan alleen als de constructie van MainApp() faalt (dus java.lang.ExceptionInInitializerError). Er gaat dus wel degelijk wat mis in de de constructor van MainApp() (nullpointer @ regel 129).
Ik denk dat die hele constructor nooit wordt aangeroepen in dit stukje code:

Java:
1
2
3
4
5
6
7
    public static MainApp get() { 
        return SingletonHolder.instance; 
    }
 
    private static class SingletonHolder { 
->        private static MainApp instance = new MainApp(); 
    }


Daar staat impliciet dat die statische variabele geïnitialiseerd moet worden, maar volgens mij werkt dat zo niet.
BalusC schreef op woensdag 09 mei 2007 @ 22:29:
In plaats van om zijn singletonprobleem te oplossen kunnen we ook wachten op het antwoord waarom hij per-se een uitvoerbare java applicatie in een singleton wil gieten. Dat je specifieke utilityklassen als een singleton ontwerpt, oké, maar een uitvoerbare applicatie? Hier steekt meer 'bad design' achter :)
Daar ben ik inderdaad ook wel benieuwd naar :)

[ Voor 24% gewijzigd door dawuss op 09-05-2007 22:35 ]

micheljansen.org
Fulltime Verslaafde Commandline Fetisjist ©


  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 30-11 11:20

voodooless

Sound is no voodoo!

BalusC schreef op woensdag 09 mei 2007 @ 22:29:
In plaats van om zijn singletonprobleem te oplossen kunnen we ook wachten op het antwoord waarom hij per-se een uitvoerbare java applicatie in een singleton wil gieten.
Zoals ik al zei, er is vermoedelijk helemaal geen singleton probleem ;)

Neemt natuurlijk niet weg dat het een vreemde ontwerpbeslissing is...

Do diamonds shine on the dark side of the moon :?


  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 30-11 11:20

voodooless

Sound is no voodoo!

dawuss schreef op woensdag 09 mei 2007 @ 22:34:
Daar staat impliciet dat die statische variabele geïnitialiseerd moet worden, maar volgens mij werkt dat zo niet.
Dat kan prima werken. Maar het gaat dus in dit geval mis, vandaar die vreemde java.lang.ExceptionInInitializerError, die je nu krijgt. De fout zit dus in die regel 129.

[ Voor 4% gewijzigd door voodooless op 09-05-2007 22:44 ]

Do diamonds shine on the dark side of the moon :?


  • 2playgames
  • Registratie: Februari 2005
  • Laatst online: 01-06 15:19
erm...mensen...is het jullie opgevallen dat het allang opgelost is?? 8)7
2playgames in "[Java] NullPointer bij Singleton"
het ging dus fout omdat mn constructor pas klaar was aan het einde van de applicatie
In plaats van om zijn singletonprobleem te oplossen kunnen we ook wachten op het antwoord waarom hij per-se een uitvoerbare java applicatie in een singleton wil gieten. Dat je specifieke utilityklassen als een singleton ontwerpt, oké, maar een uitvoerbare applicatie? Hier steekt meer 'bad design' achter
omdat de hoofdklasse dan makkelijk overval vandaan te bereiken is, zonder dat deze in allerlei constructoren meegegeven moet worden. ja, misschien is het lui en slecht ontwerp, maar richtlijnen zijn er om het makkelijk te maken, niet om per se te volgen ;)
wikipedia:
[Singleton Classes are] useful when exactly one object is needed to coordinate actions across the system.
naar mijn mening geldt dit voor mijn klasse

[ Voor 14% gewijzigd door 2playgames op 09-05-2007 23:13 ]


  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 30-11 11:20

voodooless

Sound is no voodoo!

Als je het goed ontwerpt is het helemaal niet nodig om de hoofdklasse overal in mee te geven :)

Do diamonds shine on the dark side of the moon :?

Pagina: 1