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

Java二维数组克隆后内容异常变更问题求助

问题:二维数组克隆后内容在循环结束后异常变更

我写了一个通过试错生成最优数组的方法:在if (rating < bestRating)判断里打印克隆得到的bestRation数组时,能看到逐步优化的有效数据;但while循环结束后再读取这个数组,第二维度的内容全变成了0。为什么数组内容会在判断之外发生变更?


相关代码与测试情况

数组定义

private double[][] ration //ration[0].length 始终为2

方法起始代码

private void suggestRation() {
    // 计时器
    Stopwatch suggestionWatch = new Stopwatch();
    suggestionWatch.startO();

    // 获取评分基准
    int mode = loadUserRation();
    double[][] bestRation = ration.clone();
    double bestRating = submit();

    // 最大组件数量
    int max = MainClass.getRation().getComponentList().getSize();
    int lines = MainClass.getRation().getRationGrid().length(true);
    if (max > lines) {
        max = lines;
    }

    int loops = 0;
    long lapseEnd = System.nanoTime() + (long) (duration * 1.0E9);
    long lapseMin = System.nanoTime() + (long) (duration * 1.0E8);

核心逻辑与异常代码

while (System.nanoTime() < lapseEnd) {

        switch (mode) {
        case NEW:
            int components = (new Random()).nextInt(max);
            generateNewRation(components);
            break;

        case REFINE:
            generateNewAmounts();
            break;
        case EXTEND:
            expandRation();
            break;
        }

        double rating = submit();

        if (rating < bestRating) {
            bestRation = ration.clone();
            bestRating = rating;
            
            // 这里能正确打印出优化后的数组
            for (int i = 0; i < bestRation.length; i++) {
                System.out.println(bestRation[i][0] + " " +bestRation[i][1]);
            }
        }
        loops++;

        if (bestRating < 5 && System.nanoTime() > lapseMin) {
            break;
        }
    }
    
    // 这里打印时第二列全为0,和上面最后一次输出不一致
    for (int i = 0; i < bestRation.length; i++) {
        System.out.println(bestRation[i][0] + " " + bestRation[i][1]);
    }

    ration = bestRation.clone();

触发的分支代码(REFINE模式)

private void generateNewAmounts() {

    double max_amount = Constants.FM_MAX;

    for (int i = 0; i < ration.length; i++) {
        if (ration[i][0] != -1) {
            ration[i][1] = (new Random().nextInt((int) (max_amount - 1)) + 1);
        }
    }

}

测试输出情况

  • 循环内的打印输出(每次找到更优解时):
0.0 37.0
0.0 51.0
0.0 50.0
0.0 44.0
0.0 45.0
  • 循环结束后的打印输出:
0.0 0.0
  • 预期输出:
0.0 45.0

原因与解决方案

问题根源:二维数组的浅克隆

Java中double[][]的clone()方法是浅克隆:它只会复制外层数组的引用,不会复制内层的一维数组。也就是说,bestRation = ration.clone()执行后,bestRation和ration的外层数组是不同对象,但它们的每个元素(一维数组)都指向同一个内存地址。

后续循环中调用generateNewAmounts()修改ration[i][1]时,实际上直接修改了bestRation内部引用的一维数组内容——因为二者共享内层数组。循环内打印时,是在修改前输出当前值;但循环结束前的最后几次循环可能没触发if (rating < bestRating)的更新,此时ration的内容被修改成0,bestRation还指向旧的内层数组,最终打印出的就是被后续修改后的值。

解决方案:实现深克隆

要真正复制二维数组的所有内容,需要手动实现深克隆,有两种常用方式:

方式1:手动遍历复制每个元素

替换bestRation = ration.clone()为以下代码:

bestRation = new double[ration.length][2];
for (int i = 0; i < ration.length; i++) {
    bestRation[i][0] = ration[i][0];
    bestRation[i][1] = ration[i][1];
}

方式2:使用Arrays.copyOf复制内层数组

也可以用Arrays.copyOf复制每个一维数组:

bestRation = new double[ration.length][];
for (int i = 0; i < ration.length; i++) {
    bestRation[i] = Arrays.copyOf(ration[i], ration[i].length);
}

修改后,bestRation会拥有完全独立的内存空间,后续修改ration不会影响到它,循环结束后就能保留最后一次更新的最优数组内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 17:47:05