空指针异常,即使行上没有任何内容是空的

Null pointer exception even though nothing on the line is null

我正在编写一个游戏,当我尝试绘制篮子对象时出现空指针异常,即使我在主游戏构造函数中创建了篮子,但在计时器启动之前最终绘制了篮子。错误行中涉及的唯一其他对象是绘画组件的图形对象,但我使用打印语句进行了检查,它也不为空。奇怪的是,即使我在绘制篮子的那一行出现异常,篮子图像仍然显示在框架上,但当我按下移动它的键时不会更新(移动)。这是主游戏 class、篮子 class 和完整的堆栈跟踪:

import java.awt.*;
import javax.swing.*;
import java.util.Collections;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.event.*;
import java.util.ArrayList;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class MainGame extends JPanel {
    JFrame frame;
    ArrayList<Ball> balls;
    Basket basket;
    int score;
    int level;
    Timer timer;

    public MainGame() {
        addKeyListener(new TAdapter());
        setFocusable(true);
        frame = new JFrame("Drop catch");
        frame.setSize(800, 800);
        frame.setBackground(Color.BLUE);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        this.setBackground(Color.BLUE);
        frame.getContentPane().add(this);
        //frame.getContentPane().add(textField);
        frame.setVisible(true);
        balls = new ArrayList<Ball>();
        basket = new Basket(frame.getWidth() / 2, frame.getHeight() * 2 / 3);
        timer = new Timer(20, new TimerListener());
        timer.start();
    }

    public static void main(String[] args) {
        MainGame myMainGame = new MainGame();
    }

    public void drawScore(Graphics g) {
        g.drawString(String.valueOf(score), frame.getWidth() / 10, frame.getHeight() / 10);
    }

    public void updateScore() {
        //might want something like this
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for(Ball b : balls) {
            b.draw(g);
        }
        boolean test = g == null || basket == null;
        System.out.println(test);//this prints false, so basket and g are both not null
        basket.draw(g);//this is line 57, where the exception is
        drawScore(g);
    }

    public class TimerListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            for(Ball b : balls) {
                b.update();
            }
            basket.update();
            updateScore();
            frame.repaint();
        }
    }

     private class TAdapter extends KeyAdapter {

        @Override
        public void keyReleased(KeyEvent e) {
            System.out.println("Key released");
            basket.keyReleased(e);
        }

        @Override
        public void keyPressed(KeyEvent e) {
            System.out.println("Key pressed");
            basket.keyPressed(e);
        }
    }
}
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.Graphics;
import java.io.File;

public class Basket {
    int x;
    int y;
    int vel;
    BufferedImage sprite;

    public Basket(int x_, int y_) {
        x = x_;
        y = y_;
        importImage();
    }

    public void importImage() {
        File imageFile = new File("sprites/basket.jpg");
        try {
            sprite =ImageIO.read(imageFile);
        } catch(Exception e) {e.printStackTrace();}
    }

    public void update() {
        x += vel;
    }

    public void draw(Graphics g) {
        g.drawImage(sprite, x, y, null);
    }

    //movement stuff
    //public class movementListener implements KeyListener {
        public void keyPressed(KeyEvent e) {
            if(e.equals(KeyEvent.VK_KP_LEFT) || e.equals(KeyEvent.VK_A)) {
                vel = -1;
            }
            if(e.equals(KeyEvent.VK_KP_RIGHT) || e.equals(KeyEvent.VK_D)) {
                vel = 1;
            }
            System.out.println("Key pressed in basket");
        }

        public void keyReleased(KeyEvent e) {
            vel = 0;
            System.out.println("Key released in basket");
        }

        public void keyTyped(KeyEvent e) {}
    //}
}
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at MainGame.paintComponent(MainGame.java:57)
        at java.desktop/javax.swing.JComponent.paint(JComponent.java:1074)
        at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
        at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
        at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
        at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
        at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
        at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
        at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5262)
        at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBufferedFPScales(RepaintManager.java:1707)
        at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1616)
        at java.desktop/javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1556)
        at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
        at java.desktop/javax.swing.JComponent.paint(JComponent.java:1060)
        at java.desktop/java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
        at java.desktop/sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:75)
        at java.desktop/sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:112)
        at java.desktop/java.awt.Container.paint(Container.java:2002)
        at java.desktop/java.awt.Window.paint(Window.java:3928)
        at java.desktop/javax.swing.RepaintManager.run(RepaintManager.java:876)
        at java.desktop/javax.swing.RepaintManager.run(RepaintManager.java:848)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
        at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
        at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
        at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
        at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1884)
        at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:316)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
        at java.desktop/java.awt.EventQueue.run(EventQueue.java:721)
        at java.desktop/java.awt.EventQueue.run(EventQueue.java:715)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

首先,你的测试条件是错误的,它给你 false 因为 Graphics 对象不为空。如果要检查两个对象,请使用 &&

test = grap != null && basket=!null;

其次,您不知道 Swing 生命周期,您在初始化 basket 之前调用了 frame.getContentPane().add(this);,而在初始化 basket 之前调用了 draw。我不想了解您的代码的作用,但最简单的解决方案是在将组件添加到框架之前初始化 Basket

 public MainGame() {
        addKeyListener(new TAdapter());
        setFocusable(true);
        frame = new JFrame("Drop catch");
        frame.setSize(800, 800);
        frame.setBackground(Color.BLUE);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        this.setBackground(Color.BLUE);
        basket = new Basket(frame.getWidth() / 2, frame.getHeight() * 2 / 3);//init before add 
        frame.getContentPane().add(this);
        //frame.getContentPane().add(textField);
        frame.setVisible(true);
        timer = new Timer(20, new TimerListener());
        timer.start();
    }