我有一个getter方法,返回一个不可修改的列表,如下所示:
public List<Product> getProductList() {
if (productList == null)
return new ArrayList<>();
return Collections.unmodifiableList(productList);
}我这样称呼这个getter:
List<Product> productList = new ArrayList<>(report.getProductList());然后,我将这个列表传递给另一个修改该列表的方法:
for (Product product : productList) {
product.addToAdvisoryList(advisory);
}其中,addToAdvisoryList(咨询)是:
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);
}
}运行这些代码后,原始产品列表将被修改。有人能解释一下到底发生了什么吗?怎样才能避免修改不可修改的列表呢?
发布于 2018-07-10 03:57:27
在您提供的代码中,原始的(不可修改的)列表作为参数传递给java.util.ArrayList的构造函数,一个可修改的列表。
List<Advisory> newAdvisoryList = new ArrayList<>(advisoryList);此构造函数按照迭代器返回的顺序(参见documentation )创建一个新列表,其中包含所提供的Collection的所有项。
同样的事情也发生在产品列表中:
List<Product> productList = new ArrayList<>(report.getProductList());这使得首先返回不可修改的列表是多余的。
换句话说,你不是在修改不可修改的列表。您正在创建可修改的新列表,使用来自不可修改(不可变)列表的元素,然后修改(可变)列表。
另请参阅here文档中的不可变列表。当你试图修改一个不可变的列表时,你会得到一个UnsupportedOperationException。
编辑
要回答您关于getter的问题:
“getter的目的不是返回对象的只读副本吗?”
getter用于从外部提供对私有或受保护类成员的访问。
如果您有一个类似(在您的示例中) Report的类
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的获取方法和设置方法的更多信息。
发布于 2018-07-10 04:22:03
您的列表包含可变的产品对象。
您不需要修改任何列表。这些列表包含对相同可变对象的引用,并且您正在对这些对象进行更改。这基本上是一个老问题,
为了避免这种情况,您可以让getProductList返回一个副本列表。或者,您可以将Product类设置为不可变的,这将迫使您重新考虑您的方法。
public List<Product> getProductList() {
List<Product> copies = new ArrayList<>();
for (Product product: productList)
copies.add(new Product(product)); // add this constructor
return copies;
}https://stackoverflow.com/questions/51253081
复制相似问题