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

Java调用ArrayList.add()仅更新首元素未追加新元素问题

问题现象
  • 编写国际象棋黑象(BlackBishop)类的合法移动坐标计算逻辑时,调用ArrayList.add()方法无法将元素追加到列表末尾,列表索引为0的首元素会随循环执行持续更新
  • 查阅ArrayList官方文档后尝试改用add(index, element)重载方法,问题仍然存在
  • 测试用例为实例化new BlackBishop(7,3),传入参数分别对应国际象棋棋盘第7行、第3列(C列)
原实现代码
import java.util.ArrayList;

public class BlackBishop extends Item{

BlackBishop(int y, int x){
    name='F';
    point=3;
    this.y=y;
    this.x=x;
    availableMoves();
}

public ArrayList<Integer[]> availableMoves(){
    int finalY=0;
    int finalX=0;
    Integer[] move=new Integer[2];
    ArrayList<Integer[]> avMoves=new ArrayList<>();

    for(int i=1;i<8;i++){
        if(x-i>0&&y-i>0){
            finalY=y-i;
            finalX=x-i;
            move[0]=finalY;
            move[1]=finalX;
            avMoves.add(move);
        }
        System.out.println(avMoves.get(0)[0]+" "+avMoves.get(0)[1]);
        if(x-i>0&&y+i<=8){
            finalY=y+i;
            finalX=x-i;
            move[0]=finalY;
            move[1]=finalX;
            avMoves.add(move);
        }
        System.out.println(avMoves.get(0)[0]+" "+avMoves.get(0)[1]);
        if(x+i<=8&&y-i>0){
            finalY=y-i;
            finalX=x+i;
            move[0]=finalY;
            move[1]=finalX;
            avMoves.add(move);
        }
        if(x+i<=8&&y+i<=8){
            finalY=y+i;
            finalX=x+i;
            move[0]=finalY;
            move[1]=finalX;
            avMoves.add(move);
        }
        
    }
    return avMoves;
}
}
运行输出
6 2
8 2
5 1
5 1
5 5
5 5
4 6
4 6
3 7
3 7
2 8
2 8
2 8
2 8

从输出可以看到,列表首元素的值随循环持续变化,没有按预期存储所有计算得到的合法移动坐标。

根本原因

问题和ArrayList的add方法实现无关,出在数组对象的引用逻辑上:

  1. 代码在for循环外部只创建了一次Integer[] move = new Integer[2];数组对象
  2. Java中数组是引用类型,调用avMoves.add(move)时,存入列表的不是当前move数组的内容拷贝,而是这个数组对象的内存引用
  3. 循环过程中反复修改move[0]、move[1]的值时,所有列表条目因为都指向同一个数组对象,读取到的值都会同步更新
  4. 最终整个ArrayList里存储的全是同一个数组的引用,值为循环最后一次给move数组赋值的坐标,因此每次读取索引0的元素,都会看到值被最新的计算结果覆盖。
修复方法

每次往列表添加移动坐标前,新建一个独立的Integer[]数组对象,不要复用循环外创建的同一个数组实例,保证每个列表条目指向独立的数组对象,修改操作不会互相影响。
修复后的核心逻辑代码:

public ArrayList<Integer[]> availableMoves(){
    int finalY=0;
    int finalX=0;
    ArrayList<Integer[]> avMoves=new ArrayList<>();

    for(int i=1;i<8;i++){
        if(x-i>0&&y-i>0){
            finalY=y-i;
            finalX=x-i;
            // 每次添加前创建新的数组实例
            Integer[] move=new Integer[2];
            move[0]=finalY;
            move[1]=finalX;
            avMoves.add(move);
        }
        System.out.println(avMoves.get(0)[0]+" "+avMoves.get(0)[1]);
        if(x-i>0&&y+i<=8){
            finalY=y+i;
            finalX=x-i;
            Integer[] move=new Integer[2];
            move[0]=finalY;
            move[1]=finalX;
            avMoves.add(move);
        }
        System.out.println(avMoves.get(0)[0]+" "+avMoves.get(0)[1]);
        if(x+i<=8&&y-i>0){
            finalY=y-i;
            finalX=x+i;
            Integer[] move=new Integer[2];
            move[0]=finalY;
            move[1]=finalX;
            avMoves.add(move);
        }
        if(x+i<=8&&y+i<=8){
            finalY=y+i;
            finalX=x+i;
            Integer[] move=new Integer[2];
            move[0]=finalY;
            move[1]=finalX;
            avMoves.add(move);
        }
        
    }
    return avMoves;
}

内容的提问来源于stack exchange,提问作者Emin K.L.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 01:03:17