Java Swing开发井字棋使用ActionListener出现数组越界报错
问题根因
你遇到的是Java lambda表达式的变量捕获特性导致的问题:
- 循环中注册监听器用的lambda
e -> knappar[i].setEnabled(false)没有捕获循环执行到当前步时的i值,而是捕获了i变量本身的引用 - 你的i是Fenster类的成员变量,9次循环结束后i已经自增到9,点击按钮触发lambda执行时,读取的就是此时值为9的i,访问
knappar[9]自然超出了长度为9的数组边界。
修复方案
方案1:循环内新增临时变量存储当前索引
在while循环内部定义一个final修饰的临时变量存储当前的i值,lambda中用这个临时变量替代i即可:
while(i <= 8) { final int currentIdx = i; // 新增行,存储当前循环的索引 knappar[i].setBounds(b, h, 100, 100); knappar[i].setLayout(null); knappar[i].addActionListener(e -> knappar[currentIdx].setEnabled(false)); // 替换为currentIdx knappar[i].setBackground(Color.green); this.add(knappar[i]); if (i%2 == 0) { } b = b+110; if(b > 230) { b = 10; h =h+110; } i++; }
每次循环生成的currentIdx都是独立的不可变变量,不会随后续i的自增改变,lambda捕获到的就是对应按钮的正确索引。
方案2:直接从事件对象获取被点击的按钮
不需要依赖索引定位按钮,直接从事件的源对象获取被点击的组件,从根源避免索引越界问题:
knappar[i].addActionListener(e -> { JButton clickedButton = (JButton) e.getSource(); clickedButton.setEnabled(false); });
这个方案逻辑更简洁,也不需要额外处理索引变量。
内容的提问来源于stack exchange,提问作者Dava222
相关产品推荐
相关产品推荐

