J2ME 應用受限於裝置儲存 (JAR 大小限制) 與運行記憶體 (堆疊常 < 200KB)。本文以一個簡單 MIDlet 為例,示範五大優化步驟:移除多餘功能、消除匿名內部類、善用內建類別、扁平化繼承、縮短識別名稱 (混淆器),並附贈陣列初始化優化技巧。
功能:顯示文字輸入框,內容變更時播放提示音。使用 BasicMIDlet 抽象基類、兩個匿名內部類實作 CommandListener/ItemStateListener、自訂 MainForm 繼承 Form。
評估每個功能必要性。若用戶可接受無聲音,移除 AlertType.INFO.playSound() 相關代碼。
每個類別檔 (即使空類) 約佔 200 bytes。匿名類常用於事件監聽。
優化前:兩個匿名類 (CommandListener, ItemStateListener) + MainForm 內部類。
優化後:主 MIDlet 類直接 implements CommandListener, ItemStateListener,移除所有內部類,commandAction/itemStateChanged 以參數區分來源。
Vector, Hashtable,勿自寫。Form 直接 new Form(...) 即可,無需繼承建立子類 (除非確有複用邏輯)。若抽象基類 (BasicMIDlet) 僅被一個子類繼承,合併為單一類別。雖違背 OOD 復用原則,但在 J2ME 資源極限下,體積優先於結構優雅。
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class ASO extends MIDlet implements CommandListener, ItemStateListener {
private Display display;
private Form mainForm;
private TextField tf = new TextField("Type anything", null, 20, 0);
private static final Command EXIT_CMD = new Command("Exit", Command.EXIT, 1);
public ASO() {}
protected void destroyApp(boolean u) { exitMIDlet(); }
public void exitMIDlet() { notifyDestroyed(); }
public Display getDisplay() { return display; }
protected void initMIDlet() {
mainForm = new Form("MainForm");
mainForm.addCommand(EXIT_CMD);
mainForm.setCommandListener(this);
mainForm.setItemStateListener(this);
mainForm.append(tf);
getDisplay().setCurrent(mainForm);
}
public void commandAction(Command c, Displayable d) {
if (c == EXIT_CMD) exitMIDlet();
}
public void itemStateChanged(Item item) {
if (item == tf) AlertType.INFO.playSound(getDisplay());
}
protected void pauseApp() {}
protected void startApp() throws MIDletStateChangeException {
if (display == null) { display = Display.getDisplay(this); initMIDlet(); }
}
}
Java 編譯器將 int[] a = {0,1,2,3}; 展開為四條賦值指令,增大 bytecode。
替代方案:
/data.bin 置入 JAR,運行時用 getResourceAsStream() 讀入 DataInputStream 批次載入。可用 javap -c 檢視 bytecode 驗證優化效果。
並非所有步驟適用於每個專案,但大多數 MIDP 應用可受益於:移除內部類、合併單繼承、移除 package、混淆器處理命名、資源外部化。工具自動化 (混淆器、打包腳本) 是持續優化關鍵。