向ArrayList添加非静态对象时部分存储值被覆盖的问题排查
问题排查:ArrayList中Song对象的流派被覆盖
核心问题:遍历XML生成Song对象并加入ArrayList后,所有Song的流派都被最后一次循环的内容覆盖,标题显示正常。
Song类定义
public class Song { private String title; private ArrayList<String> genre; public Song (String t, ArrayList<String> g) { title = t; genre = g; } public String getTitle () { return title; } public ArrayList<String> getGenre () { return genre; } }
现象对比
预期输出
Song Title: 8 Genres:[metal,pop,balad]
Song Title: 11 Genres:[funk,pop]
实际输出
Song Title: 8 Genres: [funk,pop]
Song Title: 11 Genres:[funk,pop]
原因分析
问题出在循环中复用了同一个auxArray对象。ArrayList属于引用类型,你创建Song对象时传入的是auxArray的内存引用,而非内容副本。后续循环中对auxArray的修改(清空、添加新流派等操作),会直接同步到所有已创建的Song对象的genre列表中——因为它们指向的是同一个ArrayList实例。
解决方案
方案1:循环内创建新的auxArray
每次循环开始时初始化新的ArrayList,确保每首歌的genre对应独立的对象:
// 循环内部 while (遍历XML节点) { ArrayList<String> auxArray = new ArrayList<>(); // 每次循环新建 // 填充当前歌曲的流派到auxArray Song song = new Song(title, auxArray); songsList.add(song); }
方案2:创建Song时传入流派列表的副本
如果需要在循环外声明auxArray,可在创建Song时传入当前auxArray的副本,避免后续修改影响已生成的Song:
// 循环内部(auxArray在循环外声明) auxArray.clear(); // 清空旧内容 // 填充当前歌曲的流派到auxArray Song song = new Song(title, new ArrayList<>(auxArray)); // 传入副本 songsList.add(song);
优化建议:修改Song构造方法增强封装
可以在Song类的构造方法中主动复制传入的流派列表,从根源上避免外部引用修改影响内部状态:
public Song(String t, ArrayList<String> g) { title = t; genre = new ArrayList<>(g); // 创建独立副本,隔离外部修改 }
内容的提问来源于stack exchange,提问作者Monstruo
相关产品推荐
相关产品推荐

