ArrayList作为对象属性无法保存值:平均值正确但列表为空
嘿,这个场景我太熟悉了!之前做数据导入的时候也踩过一模一样的坑——核心问题几乎可以确定是你用来计算平均值的列表,和对象自身的points属性不是同一个引用,下面给你拆解几种最常见的情况:
1. 填充完临时列表后,忘了赋值给对象的points属性
这是最常见的情况:你在读取TXT文件时,新建了一个临时ArrayList来存储数据,用这个临时列表算出了正确的平均值,但却没把这个临时列表赋值给对象的points字段。
举个错误示例:
// 假设你的数据对象是这样的 class DataObject { private ArrayList<Integer> points; private int average; // getter & setter public void setAverage(int average) { this.average = average; } public void setPoints(ArrayList<Integer> points) { this.points = points; } } // 你的业务代码 DataObject obj = new DataObject(); ArrayList<Integer> tempPoints = new ArrayList<>(); // 读取TXT文件,把数据加入tempPoints... tempPoints.add(4); tempPoints.add(6); tempPoints.add(8); // 计算平均值,结果正确((4+6+8)/3=6) int sum = tempPoints.stream().mapToInt(Integer::intValue).sum(); obj.setAverage(sum / tempPoints.size()); // 关键错误!忘了把填充好的tempPoints赋值给obj的points // obj.setPoints(tempPoints);
这种情况下,tempPoints里有数据,所以平均值计算正确,但obj.points还是默认的null或者空列表,自然打印的时候是空的。
解决办法很简单:计算完平均值后,一定要把临时列表通过setter或者直接赋值(如果字段是public的话,不推荐)给对象的points属性。
2. 操作了points的副本而非原列表
如果你的对象已经初始化了points列表,但你在填充数据时,不小心创建了它的副本并往副本里加数据,那原对象的points还是空的,而副本的数据用来计算平均值是正确的。
比如错误示例:
DataObject obj = new DataObject(); obj.setPoints(new ArrayList<>()); // 初始化空列表 // 错误地创建了原列表的副本 ArrayList<Integer> temp = new ArrayList<>(obj.getPoints()); temp.add(4); temp.add(6); temp.add(8); // 用副本计算平均值,结果正确 int sum = temp.stream().mapToInt(Integer::intValue).sum(); obj.setAverage(sum / temp.size());
这里temp是obj.points的一个新副本,你往temp加数据不会影响原列表,所以obj.points还是空的。
解决办法:直接操作原列表,而不是创建副本:
ArrayList<Integer> originalPoints = obj.getPoints(); originalPoints.add(4); originalPoints.add(6); originalPoints.add(8);
3. 字段初始化或封装的问题(少见但值得排查)
如果你的对象类里points字段没有正确初始化,比如:
class DataObject { private ArrayList<Integer> points; // 只声明,没初始化 private int average; }
但这种情况如果你直接往points加数据会抛出NullPointerException,而你说平均值计算正确,所以这种可能性比较小,但可以检查一下你的对象类是否正确初始化了points。
总结一下:你只需要确认计算平均值用的列表,和对象的points是同一个引用——要么把临时列表赋值给对象,要么直接操作对象的原列表,问题就能解决啦!
内容的提问来源于stack exchange,提问作者Justus

