NullPointerException再一次 - intersects()

时间:2012-07-09 09:45:43

标签: java multithreading

Ball.java

public class Ball {
    int x = 500, y = 10, speed = 1;
    GameBoard board;
    boolean keepRunning = true;
    Thread thread;

    Ball(GameBoard board) {
        this.board = board;
        new Thread(r1).start();
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    Runnable r1 = new Runnable() {
        public void run() {
            try {
                while (true) {
                    if (board.ball.intersects(board.pPaddle)) {
                        speed = -speed;
                    } else {
                        System.out.println(board.ball + " z " + board.pPaddle);
                    }
                    x -= speed;
                    board.repaint();
                    Thread.sleep(10L);

                }
            } catch (InterruptedException iex) {
            }
        }

    };
}

GameBoard.java

@SuppressWarnings("serial")
public class GameBoard extends Canvas {
    Image dbi;
    Graphics db;
    JFrame okno;
    Player p = new Player(this);
     Ball b = new Ball(this);
     Ai a = new Ai(this);
     Rectangle aiPaddle = new Rectangle(10, 590, 10, 50);
     Rectangle pPaddle = new Rectangle(10, 100, 10, 50);
     Rectangle ball = new Rectangle(500, 10, 10, 10);
    GameBoard() {
        okno = new JFrame();
        okno.setTitle("Pink Ponk");
        okno.setSize(600, 300);
        okno.getContentPane().setBackground(Color.black);
        okno.setResizable(false);
        okno.setVisible(true);
        okno.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addKeyListener(p);
    }

    public static void main(String[] args) {
        GameBoard gra = new GameBoard();
        gra.okno.add(gra);
    }

    @Override
    public void update(Graphics g) {
        pPaddle.setBounds(p.getX(), p.getY(), 10, 50);
        aiPaddle.setBounds(a.getX(), a.getY(), 10, 50);
        ball.setBounds(b.getX(), b.getY(), 10, 10);
        dbi = createImage(10, 50);
        db = dbi.getGraphics();
        paint(db);
        g.clearRect(0, 0, 600, 300);
        g.drawRect(p.getX(), p.getY(), 10, 50);
        g.fillRect(p.getX(), p.getY(), 10, 50);
        g.drawOval(b.getX(), b.getY(), 10, 10);
        g.fillOval(b.getX(), b.getY(), 10, 10);
    }

    @Override
    public void paint(Graphics g) {
        pPaddle.setBounds(p.getX(), p.getY(), 10, 50);
        aiPaddle.setBounds(a.getX(), a.getY(), 10, 50);
        ball.setBounds(b.getX(), b.getY(), 10, 10);
        g.clearRect(0, 0, 600, 300);
        g.setColor(Color.white);
        g.drawRect(p.getX(), p.getY(), 10, 50);
        g.fillRect(p.getX(), p.getY(), 10, 50);
        g.drawOval(b.getX(), b.getY(), 10, 10);
        g.fillOval(b.getX(), b.getY(), 10, 10);
    }

}

直到我编写这行代码(Ball.java中的24):

if (board.ball.intersects(board.pPaddle))

我收到错误:

  

线程“Thread-0”中的异常java.lang.NullPointerException at   来自java.lang.Thread.run的球$ 1.run(Ball.java:24)(未知来源)

我确定GameBoard.java中的矩形不是空的。我不知道该怎么做。

2 个答案:

答案 0 :(得分:1)

据我所知,有两种可能性:

  • board,传递给Ball的构造函数的参数为​​null
  • board,传递给Ball的构造函数的参数不是null,但是因为你在构造函数中启动一个线程,线程可以看到你的Ball对象部分构造(例如,ball.board可能没有已被分配)...

你应该做什么:

  1. 检查board是否为空(例如使用打印语句)
  2. 无论如何,don't start a new thread in your constructor
  3. 您可以在构造函数中创建线程,并提供另一个启动线程的方法(例如start或init)。


    完成后,您可能不会再获得NPE了。但请注意,Ball b = new Ball(this);行在Rectangle ball = new Rectangle(500, 10, 10, 10);之前执行,因此如果您在Ball的构造函数中访问board.ball,您将看到它为空。

    通常,您应该避免在构造函数或实例初始值设定项中转义this(即不要写ObjectXX o = new ObjectXX(this);之类的内容)因为this可能没有完全构造。

答案 1 :(得分:0)

球矩形很可能为空,你首先创建一个b,它会启动一个试图访问 board.ball 的线程。 ball 稍后会在GameBoard构造函数中创建。