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

为什么给每个Actor绑定的InputListener触发时返回的坐标均相同?

问题根因

你遇到的是Java匿名内部类捕获局部变量的经典问题,核心原因如下:

  • 如果你的targetField数组实际定义在双重for循环的外部,所有匿名InputListener实例捕获的都是同一个数组对象的引用。每次循环修改的都是这个数组的内容,循环结束后数组的值就是最后一次迭代的[5,5],所有回调触发时读取的都是这个数组最终的内容。
  • 哪怕你是按贴出的代码把targetField定义在循环内部,也存在隐患:数组是引用类型,只要任何地方修改了对应数组的内容,回调输出结果都会受影响。

修复方案

直接使用两个不可变的基本类型变量存储当前循环的坐标,避免引用类型带来的内容篡改问题,修改后代码如下:

for (int i = 0; i < mapSize[0]; i++) {
    for (int j = 0; j < mapSize[1]; j++) {
        hashCodes[i][j] = new Image(emptyField);
        // 用final修饰的基本类型存储坐标,匿名类捕获的是固定值而非引用
        final int targetI = i;
        final int targetJ = j;
        hashCodes[i][j].addListener(new InputListener() {
            @Override
            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                return true;
            }

            @Override
            public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                int[] targetField = new int[]{targetI, targetJ};
                System.out.println("Empty Field clicked" + Arrays.toString(targetField));
                for (Image[] imageRow : hashCodes) {
                    for (Image actualImage : imageRow) {
                        System.out.print(actualImage.hashCode() + " ");
                    }
                    System.out.println();
                }
                if (MarvelousMashup.useInfinityStone) {
                    MarvelousMashup.useInfinityStone = false;
                    MainMenu.client.getMessageHandler().sendUseInfinityStoneRequest
                            (MarvelousMashup.activeCharacter,
                                    getActualEntity(MarvelousMashup.activeCharacter).getPosition(),
                                    targetField,
                                    getStone(MarvelousMashup.useInfinityStoneID));
                }
            }
        });
        tempField.addActor(hashCodes[i][j]);
    }
}

原理说明

  • Java中匿名内部类访问外部局部变量时,要求变量是final或effectively final(赋值后不再修改)。
  • 基本类型变量被捕获时,匿名类会存储该变量的值拷贝,后续外部变量的修改不会影响拷贝值。
  • 引用类型变量被捕获时,匿名类存储的是引用的拷贝,引用指向的对象内容修改时,所有持有该引用的地方都会读到最新值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 18:03:03