TimerTask中调用ArrayList的add()后所有元素均相同的问题求助
问题原因与解决方案
嘿,这个问题其实是Java引用类型的常见小坑,我来给你拆解清楚:
问题根源
你在UpdateThread类里把PlotValuesContainer l_dataContainer声明成了类成员变量,这意味着整个UpdateThread实例只会创建这一个PlotValuesContainer对象。每次run()方法执行时,你只是修改这个同一个对象的时间戳和信号数组,然后把它添加到m_logData列表里。
因为ArrayList存储的是对象的引用,不是对象本身,所以你的列表里所有元素其实都是指向同一个PlotValuesContainer实例的引用。每次修改这个实例的属性,列表里所有"元素"看起来都会同步变化——本质上它们本来就是同一个东西。
修复方案
把PlotValuesContainer的实例化移到run()方法内部,每次执行任务时都创建一个新的实例:
private class UpdateThread extends TimerTask { @Override public boolean cancel() { return super.cancel(); } @Override public void run() { // 每次执行任务时都创建新的实例 PlotValuesContainer l_dataContainer = new PlotValuesContainer(); //store time stamp l_dataContainer.setTimeStamp(java.time.LocalDateTime.now()); //store signal values final short[] l_Array1to256 = new short[256]; for (int i = 0; i < l_Array1to256.length; i++) { l_Array1to256[i] = (short) (Math.random() * Short.MAX_VALUE); } l_dataContainer.setSignal(l_Array1to256); if (m_logData.size() > 0) { System.out.println("A - oldest: " + m_logData.get(0).getTimeStamp().toString()); } m_logData.add(l_dataContainer); System.out.println("B - newest: " + m_logData.get((m_logData.size() - 1)).getTimeStamp().toString()); for (int i = 0; i < m_logData.size(); i++) { System.out.println("C - all: " + m_logData.get(i).getTimeStamp().toString()); } } }
修复后效果
修改后,每次run()执行都会生成一个全新的PlotValuesContainer对象,设置好专属的时间戳和信号数据后再加入列表。这样列表里的每个元素都是独立的对象,各自保存自己的状态,你再遍历的时候就能看到每个元素的时间戳都是它被添加时的时间了。
内容的提问来源于stack exchange,提问作者Ulrich Gerster
相关产品推荐
相关产品推荐

