У меня есть класс, который создает корабль (класс 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);
}
}
Теперь моя проблема в том, что я получаю исключение Null Pointer Exception, когда у меня есть gameFrame.addGameObject(myShip);
Трудность в том, что когда я запускаю через отладчик, я вообще не получаю NPE (но список моих объектов по-прежнему кажется пустым).
Кроме того, я могу следить за каждым из них и все еще видеть myShip, так что я просто ссылаюсь на свой GameObject (Ship) неправильно?
Должны ли мои параметры addGameObject как-то быть более абстрактными?
Проблема в том, что вы назначаете gameFrame
внутри Runnable
, который не запускается до gameFrame
. Поэтому gameFrame
может быть нулевым в точке, которую вы вызываете gameFrame.addGameObject(myShip)
Проблема, вероятно, в том, что вы используете invokeLater, который назначается всякий раз, когда Swing чувствует себя так и, вероятно, происходит после gameFrame.addGameObject(myShip);
Это не происходит в отладчике, потому что это несколько условие гонки, в отладчике Swing вызывает runmethod перед gameFrame.addGameObject(myShip), потому что вы не можете щелкнуть достаточно быстро, чтобы выполнить этот оператор;)
Лучшим решением этой проблемы является перемещение этих операторов внутри метода 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
.
проверьте область, в которой вы инициализировали эту переменную. т.е. фигурные скобки {} вокруг нового InvadersGameFrame(). Убедитесь, что вы используете объект после его создания.