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

Java遍历List修改SDR对象属性 循环结束后值全被覆盖

ArrayList循环修改元素属性后值全被最后一次赋值覆盖

问题复现

业务逻辑为遍历List<SDR>集合,为每个元素计算并设置detail1属性,循环内打印赋值结果符合预期(分别为12、13、14),循环结束后再次遍历打印,所有元素的detail1全部变为最后一次赋值的14。
相关代码如下:

addDetails方法实现:

private List<SDR> addDetails(List<SDR> list) {
        for(SDR item: list) {
                xyz = calculateValue(item);  // 根据每个item返回不同计算值
                item.setDetail1(xyz);
                System.out.println("getDetail1 before -> " + item.getDetail1());
        }
        System.out.println();
        for(SDR item: list) {
            System.out.println("getDetail1 after -> " + item.getDetail1());
        }
} 

运行输出:

getDetail1 before -> 12
getDetail1 before -> 13
getDetail1 before -> 14

getDetail1 after -> 14
getDetail1 after -> 14
getDetail1 after -> 14

SDR类定义:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SDR {
    private String id;
    private String detail1;
}

calculateValue方法逻辑:根据传入item的id匹配数据库对应记录,返回对应的detail1字符串。

根因

和循环赋值逻辑、calculateValue方法无关,问题出在传入addDetails方法的List本身:List中存储的所有元素引用,都指向堆内存中同一个SDR对象实例。

  • 第一次循环中打印的不同值,只是因为每次循环都在修改这唯一的一个SDR对象的detail1属性,打印的是修改当下的瞬时值
  • 循环结束后,这个SDR对象的detail1属性停留在最后一次赋值的14,此时再遍历List,无论取哪个索引位置的元素,本质都是拿到同一个对象的引用,读取到的属性值自然全是14

可以加一行代码验证:在两个循环内部都打印对象的唯一标识

System.out.println("对象唯一标识:" + System.identityHashCode(item));

运行后会发现所有item打印出的标识完全一致,即可证实List中所有元素都是同一个对象。

常见错误场景

这类问题基本都是构造List时的写法错误导致,典型错误写法:

// 错误:只实例化了一次SDR对象,循环中反复修改同一个对象属性再加入List
List<SDR> list = new ArrayList<>();
SDR sdr = new SDR();
for (int i = 0; i < 3; i++) {
    sdr.setId(String.valueOf(i));
    list.add(sdr);
}

上述代码生成的List看似有3个元素,实际存储的是同一个SDR对象的3个引用,修改任意一个"元素"的属性,所有位置读取到的值都会同步变化。
如果使用@Builder构造对象,复用同一个Builder实例反复调用build()方法生成元素加入List,也会触发同样的问题。

修复方案

构造List元素时,保证每次添加元素都实例化新的SDR对象,让List中存储不同对象的独立引用即可:

// 正确:每次循环都创建新的SDR实例
List<SDR> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
    SDR sdr = new SDR();
    sdr.setId(String.valueOf(i));
    list.add(sdr);
}

如果使用Builder构造,每次生成元素都要重新走Builder创建流程,不要复用同一个Builder实例。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 23:36:37