Search code examples
javajava-menullpointerexceptionmidplcdui

NullPointerException trying to add 2 Displayables in one mobile App


I am just trying to figure out the logic of why I have an error. I'm trying to add 2 displays in 1 for the first time and switching the views using the commandListener. I thought logically I did everything right but I'm getting a null pointer exception. I never want to know the answers, I enjoy working hard so maybe if anyone can maybe ask me a question as to what I am trying to achieve that can lead me to think of the answer using your clues or hints. It will be appreciated.

import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;


public class ClassApp extends MIDlet implements CommandListener {
    private Display mydisplay;

    private TextBox d;
    private Alert alert;
    private Command c,e,f,mNextCommand,l;
    private List mList;

    public ClassApp(){

        alert = new Alert("Listen", "Do you really want to start this app?", null, null);
        alert.setTimeout(Alert.FOREVER);

        c = new Command("Exit", Command.EXIT, 2);
        e = new Command("Back", Command.BACK, 0);
        f = new Command("Alert", Command.SCREEN, 3);
        mNextCommand = new Command("Next", Command.SCREEN, 4);
        l = new Command("List", Command.SCREEN, 3);


        d = new TextBox("ClassApp", "Commander", 20, TextField.ANY | TextField.PASSWORD); 
        d.addCommand(c);
        d.addCommand(e);
        d.addCommand(f);
        d.addCommand(l);
        d.setCommandListener(this);
        mList.addCommand(mNextCommand);
        mList.setCommandListener(this);


        String[] stringElements = { "Airplane", "Car", "Hotel" };
        Image[] imageElements = { loadImage("/airplane.png"),
        loadImage("/car.png"), loadImage("/hotel.png") };

        mList = new List("Reservation type", List.IMPLICIT,
        stringElements, imageElements);




    }
    public void startApp() 
    {

        mydisplay = Display.getDisplay(this);
        mydisplay.setCurrent(d);

    }
    public void commandAction(Command j, Displayable s) 
            { 
                if(j == f)
                    mydisplay.setCurrent(alert);
                if(j == l)
                    mydisplay.setCurrent(mList);
                if (j == mNextCommand || j == List.SELECT_COMMAND) {
                int index = mList.getSelectedIndex();
                Alert alert2 = new Alert("Your selection",
                "You chose " + mList.getString(index) + ".",
                null, AlertType.INFO);
                mydisplay = Display.getDisplay(this);
                mydisplay.setCurrent(alert2, mList);
        }

                else if(j == c)
                    notifyDestroyed();
            }





    public void pauseApp() { } 
    public void destroyApp(boolean unconditional) { }
    private Image loadImage(String name) {
        Image image = null;
        try {
        image = Image.createImage(name);
        }
        catch (IOException ioe) {
        System.out.println(ioe);
        }
        return image;
    }
}

And the error I get is :

Starting emulator in execution mode
Installing suite from: http://127.0.0.1:2913/ClassApp.jad
java.lang.NullPointerException:   0
    at ClassApp.<init>(ClassApp.java:33)
    at java.lang.Class.newInstance(), bci=0
    at com.sun.midp.main.CldcMIDletLoader.newInstance(), bci=46
    at com.sun.midp.midlet.MIDletStateHandler.createMIDlet(), bci=66
    at com.sun.midp.midlet.MIDletStateHandler.createAndRegisterMIDlet(), bci=17
    at com.sun.midp.midlet.MIDletStateHandler.startSuite(), bci=27
    at com.sun.midp.main.AbstractMIDletSuiteLoader.startSuite(), bci=52
    at com.sun.midp.main.CldcMIDletSuiteLoader.startSuite(), bci=8
    at com.sun.midp.main.AbstractMIDletSuiteLoader.runMIDletSuite(), bci=161
    at com.sun.midp.main.AppIsolateMIDletSuiteLoader.main(), bci=26

Solution

  • maybe if anyone can maybe ask me a question as to what I am trying to achieve that can lead me to think of the answer using your clues or hints...

    OK here we go.

    ClassApp.java:33 part of error message says you which line of the code in ClassApp.java is problematic. Side note cryptic looking part ClassApp.<init> is telling you that bad things are happening within ClassApp constructor.

    If you count to line 33 from top, you'll probably find this:

        mList.addCommand(mNextCommand);
    

    Now, if you look for the way how mList is dealt with inside the constructor (there are about 20 lines to check), you'll discover one amusing fact that will guide you in finding what is wrong there.


    Another thing worth keeping in mind investigating bugs like that is the name NullPointerException shown at the top of stack trace. It translates to human language as

    There is null value somewhere where it should not be.

    This often indicates that some variable has not been properly assigned as you probably already noticed.


    PS.

    I'm going to continue to look for better efficiency (like moving the code into startapp)

    Initializing in startApp is rather a matter of reliability than that of efficiency.

    There are couple things that are recommended to initialize in the startApp instead of constructor. These are explained for example in tutorial MIDlet Life Cycle -> Execution States: "Typically, you'll use startApp() to allocate record stores, network connections, UI components, and such..."

    As far as I understand there is no definitive list of what is guaranteed to be safely initialized in constructor. Because of that I try to do a much initialization as possible in startApp - that way, I don't need to bother with cumbersome checks in specification for whether it is safe or not.