Java Swing猜数字游戏JButton空指针异常问题求助
解决Java Swing猜数字游戏的空指针异常及逻辑问题
核心问题分析
空指针异常根源
你在类里声明了成员变量JButton check;,但在构造函数里又重新定义了局部变量JButton check = new JButton("check");——这相当于创建了一个和成员变量同名的局部变量,类的成员变量根本没被初始化,始终为null。而pressedCheck()方法里调用的是成员变量check的addActionListener,自然会抛出Cannot invoke "javax.swing.JButton.addActionListener(...)" because "this.check" is null的异常。额外逻辑问题
wrongGuess()里的while (genNo != pInput)循环会导致无限死循环:循环内没有修改pInput的值,一旦进入这个循环,程序会一直卡死,无法响应新输入。- 每次调用
tooLow()/tooHigh()时都会执行pressedCheck(),重复给按钮添加监听器,导致一次点击触发多次事件。
修正后的代码
import javax.swing.*; import java.awt.*; import java.util.Random; class GuessNumberGUI extends JFrame { Random rand = new Random(); int genNo = rand.nextInt(100) + 1; int guesses = 1; int pInput; JLabel heading; JTextField playerGuess; JLabel output = new JLabel("Hint's appear here!", SwingConstants.CENTER); JPanel panel; JButton check; public static void main(String[] args) { new GuessNumberGUI(); } public GuessNumberGUI() { setTitle("Guess a Number"); setSize(400, 200); setDefaultCloseOperation(DISPOSE_ON_CLOSE); setLocationRelativeTo(null); // 初始化成员变量,不再定义同名局部变量 panel = new JPanel(); panel.setLayout(new BorderLayout()); panel.setBackground(Color.BLACK); heading = new JLabel("Guess a Number between 1 and 100", SwingConstants.CENTER); heading.setForeground(Color.WHITE); heading.setFont(new Font("Arial", Font.BOLD, 20)); panel.add(heading, BorderLayout.NORTH); playerGuess = new JTextField(SwingConstants.CENTER); panel.add(playerGuess, BorderLayout.CENTER); playerGuess.setBackground(Color.BLACK); playerGuess.setForeground(Color.WHITE); playerGuess.setFont(new Font("Arial", Font.BOLD, 20)); check = new JButton("check"); check.setFont(new Font("Arial", Font.BOLD, 20)); panel.add(check, BorderLayout.EAST); check.setBackground(Color.BLACK); check.setForeground(Color.WHITE); System.out.println(genNo); output.setForeground(Color.WHITE); output.setFont(new Font("Arial", Font.BOLD, 20)); panel.add(output, BorderLayout.SOUTH); add(panel); // 只添加一次监听器,避免重复绑定 check.addActionListener(e -> { try { // 增加异常处理,防止输入非数字导致崩溃 pInput = Integer.parseInt(playerGuess.getText()); checkGuess(); } catch (NumberFormatException ex) { output.setText("请输入有效数字!"); } }); setVisible(true); } public void checkGuess() { if (pInput == genNo) { output.setText("You guessed correctly! No. of tries:" + guesses); // 猜对后禁用按钮,防止重复点击 check.setEnabled(false); } else { wrongGuess(); } } private void wrongGuess() { // 移除while循环,仅做单次判断提示 if (pInput < genNo) { tooLow(); } else if (pInput > genNo) { tooHigh(); } } private void tooLow() { output.setText("Too low! Try again!"); guesses++; } private void tooHigh() { output.setText("Too high! Try again!"); guesses++; } }
关键修改说明
- 去掉构造函数中所有局部变量的重新定义,直接给类的成员变量赋值(比如
panel = new JPanel();而非JPanel panel = new JPanel();),确保成员变量被正确初始化。 - 删除
pressedCheck()方法,仅在构造函数中添加一次ActionListener,避免重复绑定事件。 - 移除
wrongGuess()里的while循环,改为单次判断提示,解决无限循环问题。 - 增加输入非数字的异常处理,防止程序崩溃。
内容的提问来源于stack exchange,提问作者Eryk Smaga
相关产品推荐
相关产品推荐

