Java 尽管属于 Collections.unmodifiableList(),但从某处修改了列表

Java List being modified from somewhere despite being of Collections.unmodifiableList()

我的程序中有三个列表。

列表是这样声明的:

ONE = 外部来源

两个=一个

三=一

我在响应用户过滤特定项目时遇到了这个问题。该函数将迭代匹配过滤项目的三个和 List.remove(index) 个项目。该函数不与 TWO 交互。尽管这两个被修改为等同于三个,尽管初始声明不再是 运行(我检查了调试器并且在修改两个时无法解决)。

我尝试将 TWO 更改为 Collections.unmodifiableList() 但它仍然被修改了?

我解决了一些严重的问题。

Object[] temp = new Object[ONE.size()];
temp=ONE.toArray(temp);
TWO = Arrays.asList(temp);

我知道太糟糕了...它之所以有效,是因为 Arrays.asList 是不可变的,但不可修改的列表肯定也是不可变的吗?

为请求者添加了代码。 初始化代码:

protected void onPostExecute(List<SpaceObject> visibleObjects){
    hideLoading();
    SpaceObject[] atom = new SpaceObject[visibleObjects.size()];
    atom=visibleObjects.toArray(atom);
    VISIBLE_OBJECTS = Arrays.asList(atom);
    SHOWING_OBJECTS = visibleObjects;
    addToView(visibleObjects);
}

正在响应删除或添加项目。

private void showSpecificItems(String itemType, Boolean remove){
    int i = 0;

    if (remove) {
        while (i < SHOWING_OBJECTS.size()){
            if(SHOWING_OBJECTS.get(i).getType().toLowerCase().matches(itemType.toLowerCase())){
                    SHOWING_OBJECTS.remove(i);
            }else{
                i++;
            }
        }
    }else{
        System.out.println("remove");
        while(i < VISIBLE_OBJECTS.size()){
            if(VISIBLE_OBJECTS.get(i).getType().toLowerCase().matches(itemType.toLowerCase())){
                SHOWING_OBJECTS.add(VISIBLE_OBJECTS.get(i));
            }
            i++;
        }
        SHOWING_OBJECTS = sortBrightest(SHOWING_OBJECTS);
    }
    addToView(SHOWING_OBJECTS);

}

如果你有这样的代码

List<Object> ONE = someMagic();

List<Object> TWO = ONE;

List<Object> THREE = ONE;

然后你有三个东西都指向同一个列表。

如果你想让它们不一样,你可以试试这样:

List<Object> ONE = someMagic();

List<Object> TWO = ONE.clone();

List<Object> THREE = ONE.clone();

通过这种方式,他们制作了实际不同的列表。

protected void onPostExecute(List<SpaceObject> visibleObjects){
    hideLoading();
    // this line is useless - you allocate an array only to immediately toss it away?!
    SpaceObject[] atom = new SpaceObject[visibleObjects.size()]; 
    atom=visibleObjects.toArray(atom);
    // this uses atom as its backing array, which comes from visibleObjects
    VISIBLE_OBJECTS = Arrays.asList(atom);
    // this obviously atom as a backing array
    SHOWING_OBJECTS = visibleObjects;
    addToView(visibleObjects);
}

因此,要解决此问题,您需要删除对该支持数组的依赖性

protected void onPostExecute(List<SpaceObject> visibleObjects){
    hideLoading();

    VISIBLE_OBJECTS = visibleObjects.clone();
    SHOWING_OBJECTS = visibleObjects.clone();

    addToView(visibleObjects); // probably bad form, but I doubt this will keep a reference, so it's "acceptable"
}

如果clone不适合你,你可以做的稍微复杂一些

protected void onPostExecute(List<SpaceObject> visibleObjects){
    hideLoading();

    VISIBLE_OBJECTS = new ArrayList(visibleObjects);
    SHOWING_OBJECTS = new ArrayList(visibleObjects);

    addToView(visibleObjects); // probably bad form, but I doubt this will keep a reference, so it's "acceptable"
}

I tried changing TWO to be a Collections.unmodifiableList() but it was still modified?

javadocs 对通过该方法创建的 不可修改的视图 说:

An unmodifiable view collection is a collection that is unmodifiable and that is also a view onto a backing collection. Its mutator methods throw UnsupportedOperationException, as described above, while reading and querying methods are delegated to the backing collection. The effect is to provide read-only access to the backing collection. ...

Note that changes to the backing collection might still be possible, and if they occur, they are visible through the unmodifiable view. Thus, an unmodifiable view collection is not necessarily immutable.

简而言之,unmodifiableList() 没有您期望的属性。如果你想要一个可变列表的不可变快照,你需要复制它。