2

所以我有以下代码:

public class Minesweeper extends MIDlet implements CommandListener {
  public static String error = "";

  public void startApp() throws MIDletStateChangeException {
    Display display = Display.getDisplay(this);

    canvas = new MCanvas();

    canvas.addCommand(exitCommand);
    canvas.addCommand(okCommand);
    canvas.addCommand(newCommand);

    canvas.setCommandListener(this);

    try{
        display.setCurrent(canvas);
    } catch (Exception e) {
        error = e.toString();
    }
  }
}

当我离开display.setCurrent(canvas);try 块之外时,应用程序失败并显示NullPointerException. 当我注释掉该行时,该应用程序可以正常工作(尽管显然没有添加画布)。所以错误是由那条线引起的,或者是那条线引起的。

所以我用 try/catch 包围了那条线。尽管错误是由该行引起的,但当该行被 try/catch 包围时,错误仍然会发生。我怎样才能发现错误?(我也试过这个Throwable,但仍然没有被抓住。

画布:

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;

public class MCanvas extends Canvas {

protected void paint(Graphics g){
    //Minesweeper.p("repaint");

    Space[] data = Minesweeper.topaint;

    for(int x=0; x<data.length; x++){
        data[x].print();

        int r = data[x].row * 10;
        int c = data[x].col * 10;
        int v = data[x].value;
        String s = "";

        //System.out.println("r:"+Integer.toString(r)+" c:"+Integer.toString(c)+" s:"+Integer.toString(v));

        g.setColor(250, 0, 0);

        //Minesweeper.p("if");

        if(data[x].open){
            switch(v){
            case 0:
                g.setColor(50, 50, 50);
                break;
            case 1:
                g.setColor(100, 50, 50);
                s = "1";
                break;
            case 2:
                g.setColor(150, 50, 50);
                s = "2";
                break;
            case 3:
                g.setColor(200, 50, 50);
                s = "3";
                break;
            case 4:
                g.setColor(250, 50, 50);
                s = "4";
                break;
            case 5:
                g.setColor(250, 100, 100);
                s = "5";
            break;
            case 6:
                g.setColor(250, 125, 125);
                s = "6";
                break;
            case 7:
                g.setColor(250, 150, 150);
                s = "7";
                break;
            case 8:
                g.setColor(250, 175, 175);
                s = "8";
                break;
            case 9:
                g.setColor(250, 200, 200);
                break;
            default:
                g.setColor(250, 100, 100);
            }
        } else {
            g.setColor(0,0,0);
        }


        g.fillRect(c, r, 10, 10);

        g.setColor(250, 250, 250);
        Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);  
        g.setFont(font);
        g.drawString(s, c+5, r+8, Graphics.HCENTER | Graphics.BASELINE);

        if(data[x].hover){
            g.setColor(250, 250, 250);
            g.drawLine(c, r, c, r+9);
            g.drawLine(c, r, c+9, r);
            g.drawLine(c+9, r, c+9, r+9);
            g.drawLine(c, r+9, c+9, r+9);
        }

        //Minesweeper.p("here?");
    }

    //Minesweeper.p("here");

    //Minesweeper.p(Minesweeper.error);

    if(Minesweeper.error != null){
        g.drawString(Minesweeper.error, 10, 10, Graphics.HCENTER | Graphics.BASELINE);
    }

    Minesweeper.p("msg:"+Minesweeper.message);

    g.setColor(0, 0, 0);
    Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_LARGE);  
    g.setFont(font);
    g.drawString(Minesweeper.message, this.getWidth()/2, this.getHeight()-10, Graphics.HCENTER | Graphics.BASELINE);

    Font fontsm = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);  
    g.setFont(fontsm);
}

protected void keyPressed(int keyCode) {
    int gameaction = getGameAction(keyCode);

    int c = Minesweeper.selected.col;
    int r = Minesweeper.selected.row;

    switch (gameaction) {
    case UP:
        Minesweeper.p("UP");

        if(r>0){
            Minesweeper.selected.leavehere();
            Minesweeper.getSpace(Minesweeper.selected.row - 1, Minesweeper.selected.col).gohere();
        }
        break;
    case DOWN:
        Minesweeper.p("DOWN");

        if(r<Minesweeper.height-1){
            Minesweeper.selected.leavehere();
            Minesweeper.getSpace(Minesweeper.selected.row + 1, Minesweeper.selected.col).gohere();
        }
        break;
    case LEFT:
        Minesweeper.p("LEFT");

        if(c>0){
            Minesweeper.selected.leavehere();
            Minesweeper.getSpace(Minesweeper.selected.row, Minesweeper.selected.col - 1).gohere();
        }
        break;
    case RIGHT:
        Minesweeper.p("RIGHT");

        if(c<Minesweeper.length-1){
            Minesweeper.selected.leavehere();
            Minesweeper.getSpace(Minesweeper.selected.row, Minesweeper.selected.col + 1).gohere();
        }
        break;
    }
    repaint();
  }
}
4

2 回答 2

1

Display.setCurrent API javadocs中所述,

...该setCurrent()方法立即返回,无需等待更改发生...

由于上述原因,setCurrent可能(并且很可能)触发的调用中可能发生的异常会通过您的 try-catch。

为了能够捕获和报告此类异常,应该研究 setCurrent 触发了哪些调用(在您的情况下,这些调用在用于Canvas 的 API javadocs,事件传递部分中进行了解释),在适当的情况下通过 try-catch 块覆盖这些并设计如果发生这些异常,则以适当的方式报告异常。

在您的情况下,try-catch 可能会包围代码MCanvas.paint(这是可能发生 NPE 的地方),并且可能会报告异常,例如通过从 catch 块Alert调用该屏幕来显示带有错误消息的适当屏幕(例如) 。setCurrent

于 2012-10-22T10:10:04.443 回答
0

如果我是你,我会继续在 MCanvas 类中插入 try/catch 块。

如果不查看更多代码,任何人都很难弄清楚 NullPointerException 发生在哪里。

从您到目前为止粘贴的代码中,我能想到的唯一问题是:

您的扫雷类是否包含一个名为 topaint 的静态对象空间数组?您是否声明了它但可能忘记用数据填充它?

Space[] topaint = new Space[20]; // Declared, but nothing in it yet.

尝试访问 Minesweeper.topaint[0] 将给出 NullPointerException,除非您也这样做

topaint[0] = new Space();
于 2012-10-20T12:53:42.130 回答