今天改代碼的時候,遇到一個很郁悶的問題,J2me 程序運行時拋出一個空指針異常,經過反復研究,發現問題所在,的確是自己的基礎知識不過關導致。
參考文章如下:http://www.jcwcn.com/html/Java/10_43_37_918.htm
在改普通例程變mvc架構例程的過程中,學到了太多的東西,這些天的工作筆記和學習心得記敘著這一切。
簡單說明一下,源程序是個電話簿例程,就一個文件,所有的事務邏輯處理視圖都寫在一起,我要做的工作就是將其分離開來,按照MVC架構的模式重新改寫。
源程序中有這樣一段,啟動后顯示mainForm主菜單界面
public void startApp() {
mainForm();
}
public void mainForm() {
List l = new List("我的電話本", Choice.IMPLICIT);
l.append("查看所有電話", null);
l.append("新增電話記錄", null);
l.append("查找電話記錄", null);
l.append("退出電話本", null);
l.setCommandListener(this);
display.setCurrent(l);
}
現在我要把這個mainForm從中主程序分離出來,單獨提出來寫在ui的包中,不過,出現了空指針異常
java.lang.NullPointerException
java.lang.NullPointerException
at com.wiser.mvctest.ui.UIController.setCurrent(+5)
at com.wiser.mvctest.ui.UIController.displayWelcome(+8)
at com.wiser.mvctest.ui.UIController.init(+16)
at com.wiser.mvctest.AddrBookMIDlet.startApp(+19)
at javax.microedition.midlet.MIDletProxy.startApp(+7)
at com.sun.midp.midlet.Scheduler.schedule(+270)
at com.sun.midp.main.Main.runLocalClass(+28)
at com.sun.midp.main.Main.main(+116)
單提出來的MainMenuForm文件代碼如下
package com.wiser.mvctest.ui;
import javax.microedition.lcdui.*;
import com.wiser.mvctest.ui.UIController;
import javax.microedition.lcdui.List;
public class MainMenuForm extends List implements CommandListener {
private UIController uicontroller;
public MainMenuForm(UIController uicontroller) {
super("我的電話本", Choice.IMPLICIT);// 調用父類list的構造方法
this.uicontroller = uicontroller;
this.append("查看所有電話", null);
this.append("新增電話記錄", null);
this.append("查找電話記錄", null);
this.append("退出電話本", null);
this.setCommandListener(this);
}
public void commandAction(Command c, Displayable s) {
if (c == List.SELECT_COMMAND) {
List temp = (List) s;
switch (temp.getSelectedIndex()) {
case 0: // 選擇0,則傳EVENT_ALL_LIST_FORM這個參數到handleEvent方法,查看所有電話
uicontroller.handleEvent(
UIController.EventID.EVENT_ALL_LIST_FORM, null);
break;
case 1:// 選擇1,則傳EVENT_NEW_RECORD_FORM這個參數到handleEvent方法,新增電話記錄
uicontroller.handleEvent(
UIController.EventID.EVENT_NEW_RECORD_FORM, null);
break;
case 2:// 選擇2,則傳EVENT_SEARCH_RECORD_FORM這個參數到handleEvent方法,查找電話記錄
uicontroller.handleEvent(
UIController.EventID.EVENT_SEARCH_RECORD_FORM, null);
break;
case 3:// 選擇3,則傳EVENT_EXIT_FORM這個參數到handleEvent方法,退出電話本
uicontroller.handleEvent(UIController.EventID.EVENT_EXIT_FORM,
null);
break;
default:
break;
}
}
}
}
UIController是我寫的一個界面控制器,其中要求顯示MainMenuForm界面的源代碼如下
public void init() {
mainMenuForm = new MainMenuForm(this);
setCurrent(mainMenuForm);
}
初始化MainMenuForm后,將其傳入setCurrent。
那么很明顯上面的MainMenuForm界面代碼是沒有錯誤的,而且,在異常里看,問題應該就出在UIController的setCurrent,那么這個空指針到底是為什么呢?在網上搜索了一下,發現一個人的學習筆記,他的問題是構造函數加了void的問題,而我的構造函數是正確的;再查看api,setCurrent要求的參數是setCurrent(Displayable dis),而里面的MainMenuForm也已經初始化了,為什么還找不到呢?
這就是我當時的想法,很混亂,迷惑,而實際上這和MainMenuForm沒有關系,空指針空的是當前的界面對象,也就是程序最開始什么界面都沒有,或者說就是display這個對象是空的,那么如果display是空的,那他的方法setCurrent自然不能用,這才是原因所在,現在我在UIController的init方法中添加這樣一句
this.display = Display.getDisplay(addrbookmidlet); // addrbookmidlet在UIController構造函數中得到
這樣就可以了。
問題解決完了,對J2ME的理解又深了一步,并且對java的基礎知識也進一步鞏固了。
待我理清思路再重新來看一下,現在繼續工作。