Java ArrayList.clear()方法的行为是否一致?

时间:2015-06-18 05:27:30

标签: java arraylist instance

Java中的clear()方法是否使ArrayList中的元素为空,或者只释放其引用并使值保持活动状态。

我将ArrayList中的所有对象分配给另一个对象,然后清除它。清除后,指定的对其他对象的引用会产生不一致的结果。另一方面,如果我创建一个新的ArrayList对象而不是清除它可以正常工作。

ArrayList <Condition> conditionList = new ArrayList<Condition>();    
Risk riskObject = new Risk();
for (int i =0; i<10; i++) {         
    if(some-condition){
                    addElemetsToConditionList();

                }else{
                    addElemetsToConditionList();            
                    riskObject.setConditions(conditionList); // Setter which sets condition list to risk object. 

                    Risk newRiskObject = new Risk();
                    riskObject = newRiskObject;

//                  conditionList = new ArrayList<Condition>();
                    conditionList.clear();

                }
            }

2 个答案:

答案 0 :(得分:4)

在内部,null它的后备缓冲区中的所有元素(删除它具有的引用)并将其大小设置为0

/**
 * Removes all of the elements from this list.  The list will
 * be empty after this call returns.
 */
public void clear() {
    modCount++;

    // clear to let GC do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

您对外部数据的任何引用仍然有效,只是ArrayList不再维护对它们的引用

我相信你的问题就在这里......

riskObject.setConditions(conditionList);

您正在将ArrayList的实例传递给riskObject然后清除它,它正在共享同一个实例。

相反,您可以创建ArrayList

的新实例
riskObject.setConditions(new ArrayList(conditionList));

其中包含conditionList内容的副本,因此当您清除它时,您传递给riskObject的引用将不会受到影响,或者正如您已经完成的那样,创建一个新的ArrayList用于您的继续处理,这对您来说似乎最合乎逻辑。

答案 1 :(得分:3)

如果riskObject.setConditions(conditionList);conditionList个实例中存储对riskObject的引用,则调用conditionList.clear()也会清除riskObject所持有的列表引用的元素实例,因为它引用同一个实例。

您可以通过创建防御性副本来避免它:

public void setConditions (List<Condition> conditions)
{
    this.conditions = new ArrayList<> (conditions);
}

这比将List的副本传递给setConditions类的Risk方法更好,因为它不依赖于使用{{1}的代码的实现类正常运行。