Java NullPointerException 即使变量有值
Java NullPointerException even though the variable has a value
我目前正在开发一个用 Java 编写的游戏。
为此,我使用了 JFrames、JPanels 和 JButtons。
要select你想玩的关卡,你要select一个世界,然后选择一个关卡。
启动游戏后,我的 WorldSelection
的新实例被创建,按下按钮后,选定的世界被设置,LevelSelection
的新实例被创建。
在此处按下按钮时,将设置级别。
这是我的问题:
在Game
class中,update
方法每秒检查selected世界和关卡60次,如果两者都有selected 值,它创建一个 Stage
/Level
.
的新实例
我按下按钮设置 Level
的那一刻,我得到一个 NullPointerException
,即使它检查的值有一个值。
这种情况不会一直发生;一半时间它工作(没有抛出异常),另外 50% 抛出异常。
Exception in thread "main" java.lang.NullPointerException
at Game.update(Game.java:41)
at Game.run(Game.java:23)
at Game.start(Game.java:34)
at Game.<init>(Game.java:10)
at Game.main(Game.java:77)
这是我的代码:
游戏class:
public class Game {
private boolean running;
private WorldSelection ws;
private boolean chosen = false;
public Game() {
ws = new WorldSelection();
start();
}
public void run() { // game loop
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
update();
delta--;
}
if (System.currentTimeMillis() - timer == 1000) {
timer += 1000;
}
}
}
public void start() {
running = true;
run();
}
private void update() {
if (!chosen) {
if (ws.getWorld() == 1) {
if (ws.ls.getLevel() == 1) {
chosen = true;
//creates new stage here
}
if (ws.ls.getLevel() == 2) {
chosen = true;
//creates new stage here
}
if (ws.ls.getLevel() == 3) {
chosen = true;
//creates new stage here
}
}
else if (ws.getWorld() == 2) {
if (ws.ls.getLevel() == 1) {
chosen = true;
//creates new stage here
}
if (ws.ls.getLevel() == 2) {
chosen = true;
//creates new stage here
}
if (ws.ls.getLevel() == 3) {
chosen = true;
//creates new stage here
}
}
}
else {
//game updates here
}
}
public static void main(String[] args) {
Game game = new Game();
}
}
世界选择class:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class WorldSelection implements ActionListener {
public JFrame frame;
private int width, height;
private int world = 0;
private JButton button1;
public LevelSelection ls;
private JPanel panel;
public WorldSelection() {
this.width = 900;
this.height = 506;
frame = new JFrame();
frame.setSize(width, height);
frame.setResizable(false);
frame.setTitle("Quentins Adventure");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
panel = new JPanel();
panel.setBackground(Color.black);
button1 = new JButton("World 1");
button1.setBackground(Color.LIGHT_GRAY);
button1.setSize(120, 44);
button1.setLocation(80, 350);
button1.addActionListener(this);
panel.add(button1);
frame.add(panel);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1){
setWorld(1);
ls = new LevelSelection(235,268);
frame.setVisible(false);
}
}
public int getWorld() {
return world;
}
public void setWorld(int world) {
this.world = world;
}
}
LevelSelection class:
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class LevelSelection implements ActionListener {
public JFrame frame;
private int width, height, buttonSize = 50;
private int level = 0;
private JButton button1;
private Font font;
private JPanel panel;
public LevelSelection(int bPosX,int bPosY) {
this.width = 900;
this.height = 506;
frame = new JFrame();
frame.setSize(width, height);
frame.setResizable(false);
frame.setTitle("Quentins Adventure - Wold Selection");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
panel = new JPanel();
panel.setBackground(Color.black);
button1 = new JButton("1");
button1.setBackground(Color.LIGHT_GRAY);
button1.setFont(font);
button1.setSize(buttonSize, buttonSize);
button1.setLocation(bPosX, bPosY);
button1.addActionListener(this);
panel.add(button1);
frame.add(panel);
frame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1){
setLevel(1);
frame.dispose();
}
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
}
你setWorld
然后ls = new LevelSelection(235, 268);
表示有时刻ws.getWorld() == 1
为真,而ws.ls
为null
。
但这不仅仅是您的代码有问题。您的代码不是线程安全的,这可能会导致大量很难找到的错误。
在您的 class WorldSelection
中,创建了 class LevelSelection
的引用,但是
在 ActionPerformed()
中初始化。因此,在引用之前
LevelSelection ls
指向 null。
我目前正在开发一个用 Java 编写的游戏。 为此,我使用了 JFrames、JPanels 和 JButtons。
要select你想玩的关卡,你要select一个世界,然后选择一个关卡。
启动游戏后,我的 WorldSelection
的新实例被创建,按下按钮后,选定的世界被设置,LevelSelection
的新实例被创建。
在此处按下按钮时,将设置级别。
这是我的问题:
在Game
class中,update
方法每秒检查selected世界和关卡60次,如果两者都有selected 值,它创建一个 Stage
/Level
.
我按下按钮设置 Level
的那一刻,我得到一个 NullPointerException
,即使它检查的值有一个值。
这种情况不会一直发生;一半时间它工作(没有抛出异常),另外 50% 抛出异常。
Exception in thread "main" java.lang.NullPointerException
at Game.update(Game.java:41)
at Game.run(Game.java:23)
at Game.start(Game.java:34)
at Game.<init>(Game.java:10)
at Game.main(Game.java:77)
这是我的代码:
游戏class:
public class Game {
private boolean running;
private WorldSelection ws;
private boolean chosen = false;
public Game() {
ws = new WorldSelection();
start();
}
public void run() { // game loop
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
update();
delta--;
}
if (System.currentTimeMillis() - timer == 1000) {
timer += 1000;
}
}
}
public void start() {
running = true;
run();
}
private void update() {
if (!chosen) {
if (ws.getWorld() == 1) {
if (ws.ls.getLevel() == 1) {
chosen = true;
//creates new stage here
}
if (ws.ls.getLevel() == 2) {
chosen = true;
//creates new stage here
}
if (ws.ls.getLevel() == 3) {
chosen = true;
//creates new stage here
}
}
else if (ws.getWorld() == 2) {
if (ws.ls.getLevel() == 1) {
chosen = true;
//creates new stage here
}
if (ws.ls.getLevel() == 2) {
chosen = true;
//creates new stage here
}
if (ws.ls.getLevel() == 3) {
chosen = true;
//creates new stage here
}
}
}
else {
//game updates here
}
}
public static void main(String[] args) {
Game game = new Game();
}
}
世界选择class:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class WorldSelection implements ActionListener {
public JFrame frame;
private int width, height;
private int world = 0;
private JButton button1;
public LevelSelection ls;
private JPanel panel;
public WorldSelection() {
this.width = 900;
this.height = 506;
frame = new JFrame();
frame.setSize(width, height);
frame.setResizable(false);
frame.setTitle("Quentins Adventure");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
panel = new JPanel();
panel.setBackground(Color.black);
button1 = new JButton("World 1");
button1.setBackground(Color.LIGHT_GRAY);
button1.setSize(120, 44);
button1.setLocation(80, 350);
button1.addActionListener(this);
panel.add(button1);
frame.add(panel);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1){
setWorld(1);
ls = new LevelSelection(235,268);
frame.setVisible(false);
}
}
public int getWorld() {
return world;
}
public void setWorld(int world) {
this.world = world;
}
}
LevelSelection class:
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class LevelSelection implements ActionListener {
public JFrame frame;
private int width, height, buttonSize = 50;
private int level = 0;
private JButton button1;
private Font font;
private JPanel panel;
public LevelSelection(int bPosX,int bPosY) {
this.width = 900;
this.height = 506;
frame = new JFrame();
frame.setSize(width, height);
frame.setResizable(false);
frame.setTitle("Quentins Adventure - Wold Selection");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
panel = new JPanel();
panel.setBackground(Color.black);
button1 = new JButton("1");
button1.setBackground(Color.LIGHT_GRAY);
button1.setFont(font);
button1.setSize(buttonSize, buttonSize);
button1.setLocation(bPosX, bPosY);
button1.addActionListener(this);
panel.add(button1);
frame.add(panel);
frame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1){
setLevel(1);
frame.dispose();
}
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
}
你setWorld
然后ls = new LevelSelection(235, 268);
表示有时刻ws.getWorld() == 1
为真,而ws.ls
为null
。
但这不仅仅是您的代码有问题。您的代码不是线程安全的,这可能会导致大量很难找到的错误。
在您的 class WorldSelection
中,创建了 class LevelSelection
的引用,但是
在 ActionPerformed()
中初始化。因此,在引用之前
LevelSelection ls
指向 null。