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

Does the Java ArrayList.clear() method behave consistently?

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();

                }
            }

在内部,它 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 供您继续处理,这对您来说似乎最合乎逻辑。

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

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

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

这比将 List 的副本传递给 Risk class 的 setConditions 方法要好,因为它不依赖于使用的代码的实现Risk class 才能正常运行。