You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java记忆游戏开发报错求助:内部类引用局部变量需为final

解决Java内部类引用局部变量的错误问题

你遇到的错误是因为匿名内部类(ActionListener)引用了非final/非有效final的局部变量index。Java要求内部类引用的局部变量必须是final或者有效final(即变量赋值后不再被修改),因为内部类会保留变量的副本,如果外部变量被修改,副本和原变量的值会不一致,导致逻辑错误。你的代码中index在循环里不断执行index++,属于被修改的变量,所以不符合要求。

修改后的代码

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MemoryGame extends JFrame 
{
    private JButton[][] buttons = new JButton[4][4];
    private Color[] colors = {Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW};
    private List<Color> colorList = new ArrayList<>();
    private int score = 0;
    // 新增变量记录已点击的按钮和颜色,修复游戏逻辑
    private JButton firstClicked = null;
    private Color firstColor = null;

    public MemoryGame() 
    {
        setTitle("Memory Game");
        setSize(400, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(4, 4));

        // 填充颜色列表,每种颜色两个
        for (int i = 0; i < 2; i++) 
        {
            for (Color color : colors) 
            {
                colorList.add(color);
            }
        }
        // 打乱颜色顺序
        Collections.shuffle(colorList);

        int index = 0;
        for (int i = 0; i < 4; i++) 
        {
            for (int j = 0; j < 4; j++) 
            {
                JButton button = new JButton();
                button.setBackground(Color.GRAY);
                buttons[i][j] = button;
                add(button);
                // 关键修改:在创建内部类前,将当前index赋值给有效final变量
                final int currentIndex = index;
                button.addActionListener(new ActionListener() 
                {
                    @Override
                    public void actionPerformed(ActionEvent e) 
                    {
                        JButton clickedButton = (JButton) e.getSource();
                        // 如果按钮已经禁用,直接返回
                        if (!clickedButton.isEnabled()) {
                            return;
                        }
                        Color color = colorList.get(currentIndex);
                        clickedButton.setBackground(color);

                        // 修复游戏逻辑:处理两次点击匹配
                        if (firstClicked == null) {
                            // 第一次点击,记录按钮和颜色
                            firstClicked = clickedButton;
                            firstColor = color;
                            clickedButton.setEnabled(false);
                        } else {
                            // 第二次点击,判断是否匹配
                            if (color.equals(firstColor) && clickedButton != firstClicked) {
                                // 匹配成功,禁用两个按钮,分数加1
                                clickedButton.setEnabled(false);
                                score++;
                                if (score == 8) {
                                    JOptionPane.showMessageDialog(MemoryGame.this, "你赢了!");
                                    System.exit(0);
                                }
                                // 重置点击记录
                                firstClicked = null;
                                firstColor = null;
                            } else {
                                // 匹配失败,延迟恢复按钮状态
                                clickedButton.setEnabled(false);
                                Timer timer = new Timer(1000, new ActionListener() {
                                    @Override
                                    public void actionPerformed(ActionEvent e) {
                                        firstClicked.setBackground(Color.GRAY);
                                        clickedButton.setBackground(Color.GRAY);
                                        firstClicked.setEnabled(true);
                                        clickedButton.setEnabled(true);
                                        firstClicked = null;
                                        firstColor = null;
                                    }
                                });
                                timer.setRepeats(false);
                                timer.start();
                            }
                        }
                    }
                });
                index++;
            }
        }
        setVisible(true);
    }

    public static void main(String[] args) 
    {
        new MemoryGame();
    }
}

修改说明

  • 解决变量引用错误:在创建ActionListener之前,将当前的index赋值给final int currentIndex,这个变量赋值后不再修改,属于有效final变量,内部类可以安全引用。
  • 修复游戏逻辑:原代码点击按钮后直接匹配所有同色按钮,不符合记忆游戏的规则。新增firstClicked和firstColor变量记录第一次点击的按钮和颜色,第二次点击时判断是否匹配:
    • 匹配成功:禁用两个按钮,分数增加,全部匹配完则提示胜利。
    • 匹配失败:延迟1秒后恢复两个按钮的灰色背景和可点击状态。

内容的提问来源于stack exchange,提问作者NanoBot1000

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 01:31:20