首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当从Collections.unmodifiableList (Java8SE)创建新的ArrayList时,它是如何被修改的?

当从Collections.unmodifiableList (Java8SE)创建新的ArrayList时,它是如何被修改的?
EN

Stack Overflow用户
提问于 2018-07-10 03:53:11
回答 2查看 2.8K关注 0票数 2

我有一个getter方法,返回一个不可修改的列表,如下所示:

代码语言:javascript
复制
public List<Product> getProductList() {
    if (productList == null)
        return new ArrayList<>();
    return Collections.unmodifiableList(productList);
}

我这样称呼这个getter:

代码语言:javascript
复制
List<Product> productList = new ArrayList<>(report.getProductList());

然后,我将这个列表传递给另一个修改该列表的方法:

代码语言:javascript
复制
for (Product product : productList) {
    product.addToAdvisoryList(advisory);
}

其中,addToAdvisoryList(咨询)是:

代码语言:javascript
复制
public void addToAdvisoryList(Advisory advisory) {
    if (advisoryList == null) {
        setAdvisoryList(Collections.singletonList(advisory));
    } else if (!isContainedAdvisory(advisoryList, advisory)) {
        List<Advisory> newAdvisoryList = new ArrayList<>(advisoryList);
        newAdvisoryList.add(advisory);
        setAdvisoryList(newAdvisoryList);
    }
}

运行这些代码后,原始产品列表将被修改。有人能解释一下到底发生了什么吗?怎样才能避免修改不可修改的列表呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-10 03:57:27

在您提供的代码中,原始的(不可修改的)列表作为参数传递给java.util.ArrayList的构造函数,一个可修改的列表。

代码语言:javascript
复制
List<Advisory> newAdvisoryList = new ArrayList<>(advisoryList);

此构造函数按照迭代器返回的顺序(参见documentation )创建一个新列表,其中包含所提供的Collection的所有项。

同样的事情也发生在产品列表中:

代码语言:javascript
复制
List<Product> productList = new ArrayList<>(report.getProductList());

这使得首先返回不可修改的列表是多余的。

换句话说,你不是在修改不可修改的列表。您正在创建可修改的新列表,使用来自不可修改(不可变)列表的元素,然后修改(可变)列表。

另请参阅here文档中的不可变列表。当你试图修改一个不可变的列表时,你会得到一个UnsupportedOperationException

编辑

要回答您关于getter的问题:

“getter的目的不是返回对象的只读副本吗?”

getter用于从外部提供对私有或受保护类成员的访问。

如果您有一个类似(在您的示例中) Report的类

代码语言:javascript
复制
public class Report {

    private List<Product> products;

    public void setProducts(List<Product> products) {
        this.products = products;
    }

    public List<Product> getProducts() {
        return products;
    }

}

getProducts使列表可以从类的外部访问(因此,如果列表是可变的,则可以添加或删除元素)。这类事情通常是用Java bean完成的,尽管它的用法存在争议(请考虑用不会不必要地公开状态信息的方法来替换getter和setter)。在任何情况下,请参阅here以了解有关根据Oracle的获取方法和设置方法的更多信息。

票数 0
EN

Stack Overflow用户

发布于 2018-07-10 04:22:03

您的列表包含可变的产品对象。

您不需要修改任何列表。这些列表包含对相同可变对象的引用,并且您正在对这些对象进行更改。这基本上是一个老问题,

为了避免这种情况,您可以让getProductList返回一个副本列表。或者,您可以将Product类设置为不可变的,这将迫使您重新考虑您的方法。

代码语言:javascript
复制
public List<Product> getProductList() {
    List<Product> copies = new ArrayList<>();
    for (Product product: productList)
        copies.add(new Product(product)); // add this constructor

    return copies;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51253081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档