Kotlin嵌套ArrayList值自动变更:旧列表值被新输入值覆盖
问题原因与解决方法
问题根源
你遇到的问题是因为所有Question实例的answer字段都指向同一个answers ArrayList对象。Kotlin中ArrayList属于引用类型,传递给构造函数时,传递的是对象的内存地址而非集合副本。后续调用answers.clear()和添加新元素,本质是在修改同一块内存中的集合,因此所有引用它的Question实例都会同步看到变化。
解决方案
有三种常见修复方式:
1. 每次创建新的ArrayList对象
不再复用同一个answers,添加新Question前初始化全新的ArrayList:
// 第一个Question val answers1 = ArrayList<String>().apply { add("1234") add("234") } questions.add(Question("1","1","1", answers1)) Log.d("12345", questions.toString()) // 第二个Question,创建新的ArrayList val answers2 = ArrayList<String>().apply { add("5678") add("789") } questions.add(Question("2","2","2", answers2)) Log.d("12345", questions.toString())
2. 传递ArrayList的副本给Question
构造Question时传入原集合的拷贝,让每个Question持有独立集合:
var answers = ArrayList<String>() answers.add("1234") answers.add("234") // 传入ArrayList的副本 questions.add(Question("1","1","1", ArrayList(answers))) Log.d("12345", questions.toString()) answers.clear() answers.add("5678") answers.add("789") // 再次传入副本 questions.add(Question("2","2","2", ArrayList(answers))) Log.d("12345", questions.toString())
也可使用answers.toMutableList()生成可变副本,效果一致。
3. 修改Question类,使用不可变集合(推荐)
若无需后续修改Question的answer集合,建议将字段改为不可变List<String>,从根源避免意外修改:
data class Question( var id: String, var question: String, var correct: String, var answer: List<String> // 改为不可变List )
使用时传入集合副本或新集合:
var answers = ArrayList<String>() answers.add("1234") answers.add("234") questions.add(Question("1","1","1", answers.toList())) Log.d("12345", questions.toString()) answers.clear() answers.add("5678") answers.add("789") questions.add(Question("2","2","2", answers.toList())) Log.d("12345", questions.toString())
验证效果
修改后两次Log输出将变为:
D/12345: [Question(id=1, question=1, correct=1, answer=[1234, 234])]
D/12345: [Question(id=1, question=1, correct=1, answer=[1234, 234]), Question(id=2, question=2, correct=2, answer=[5678, 789])]
内容的提问来源于stack exchange,提问作者Rahul R
相关产品推荐
相关产品推荐

