我有一些创建Ship的类(Ship扩展GameObject类)并尝试将其添加到gameBoard。 为此,它告诉gameFrame按如下方式添加对象:
public void startNewGame() {
Ship myShip = new Ship(GAME_BOARD_WIDTH / 2, GAME_BOARD_HEIGHT-1, SHIP_WIDTH,
SHIP_HEIGHT);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gameFrame = new InvadersGameFrame();
}
});
gameFrame.addGameObject(myShip); //Problem line
gameFrame.repaint();
}
gameFrame然后调用:
GameBoard gameBoard = new GameBoard();
...
...
public void addGameObject(GameObject ob) {
gameBoard.addGameObject(ob);
}
反过来又打电话:
public class GameBoard extends JPanel implements GameData{
private JPanel gameBoard;
private List<GameObject> objects = new ArrayList<>();
public GameBoard() {
gameBoard = new JPanel();
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
setBackground(Color.black);
g.setColor(Color.RED);
for(GameObject ob : objects){
g.drawOval(ob.x, ob.y, ob.width, ob.height);
}
}
//Places object into list for drawing upon next repaint.
public void addGameObject(GameObject ob) {
objects.add(ob);
}
}
现在我的问题是,当我gameFrame.addGameObject(myShip);
时,我收到一个空指针异常
棘手的是当我通过调试器运行时根本没有收到NPE(但我的对象列表似乎仍然是空的)。
另外,我可以跟进每一个并仍然看到myShip,所以我只是引用我的GameObject(Ship)错了吗?
我的addGameObject参数应该更抽象吗?
答案 0 :(得分:4)
问题是你在gameFrame
内部分配了Runnable
,直到稍后才会运行。因此,在您调用gameFrame
gameFrame.addGameObject(myShip)
可能为null
答案 1 :(得分:2)
问题可能是你使用的invokeLater,只要Swing感觉像是这样,可能会在 gameFrame.addGameObject(myShip)之后发生;
这在调试器中不会发生,因为它在某种程度上是竞争条件,在调试器中Swing在gameFrame.addGameObject(myShip)之前调用runmethod,因为你无法快速点击以预先发出该语句;)
答案 2 :(得分:1)
此问题的最佳解决方案是在run
方法中移动这些语句,如下所示:
public void startNewGame() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Ship myShip = new Ship(GAME_BOARD_WIDTH / 2, GAME_BOARD_HEIGHT-1,
SHIP_WIDTH, SHIP_HEIGHT);
gameFrame = new InvadersGameFrame();
gameFrame.addGameObject(myShip); //Problem line
gameFrame.repaint();
}
});
}
这样做,4个语句将按预期的顺序运行,并且在需要时该属性不会是null
。
答案 3 :(得分:0)
检查初始化该变量的范围。即新InvadersGameFrame()周围的花括号{}。 确保在创建对象后使用该对象