空指针异常,即使行上没有任何内容是空的
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();
}
我正在编写一个游戏,当我尝试绘制篮子对象时出现空指针异常,即使我在主游戏构造函数中创建了篮子,但在计时器启动之前最终绘制了篮子。错误行中涉及的唯一其他对象是绘画组件的图形对象,但我使用打印语句进行了检查,它也不为空。奇怪的是,即使我在绘制篮子的那一行出现异常,篮子图像仍然显示在框架上,但当我按下移动它的键时不会更新(移动)。这是主游戏 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();
}