创建集合的副本
Creating a copy of a collection
我正在阅读 J. Bloch 的有效 Java,现在我在关于避免 returning null
s,但 returning 空集合的部分.这是该部分的代码示例:
// The right way to return a copy of a collection
public List<Cheese> getCheeseList() {
if (cheesesInStock.isEmpty())
return Collections.emptyList(); // Always returns same list
else
return new ArrayList<Cheese>(cheesesInStock);
}
我真的无法理解如果 cheesesInStock.isEmpty()
只 returning cheesesInStock
有什么问题。为什么 return 预定义的 Collections.emptyList()
更好。如果我们 return cheesesInStock
相反,我们可能会遇到什么样的麻烦。
如果方法 returns cheesesInStock
- 调用者可能会向列表中添加一些奶酪。
这是一种不好的做法,因为您可能想要控制添加过程。
因为
- 您将使用具有单例模式的
Collections.emptyList();
节省资源。
- 它是类型安全的
- 列表是不可变的(无法修改)
还可以 look at the API 你可以找到:
Returns the empty list (immutable). This list is serializable.
This example illustrates the type-safe way to obtain an empty list:
List<String> s = Collections.emptyList();
Implementation note: Implementations of this method need not create a separate List object for each call. Using this method is likely to have comparable cost to using the like-named field. (Unlike this method, the field does not provide type safety.)
这里的想法更多是关于安全对象发布或共享,返回对可变列表的引用允许调用者改变原始列表,这通常是一个坏主意。如果列表或一般对象是不可变的,那么您不需要这样做,例如 String 是不可变的,因此共享它是安全的。
String getString(){
return someString; // no need to copy
}
共享可变状态有两个主要问题:
- 当事情可以从任何地方发生变异时,很难检查程序的正确性。
- 线程安全变得更加困难,因为它需要同步,这通常是困难且昂贵的。
如果您直接 return cheesesInStock
,您 return 引用了与您所反对的相同的 List
(而不是它);因此,获取此列表的人所做的任何更改都将反映在对象的内部表示中。示例:
List<Cheese> list = myObject.getCheeseList();
list.add(new Cheese()); // this also affects the list inside myObject
为防止出现这种情况,最好使用 return 列表副本而不是 new ArrayList<Cheese>(previousList)
。请注意,除了 return 创建新的 List
,您还可以 return 使用 Collections.unmodifiableList
的不可修改的 List
视图:这具有相同的目标 -防止调用代码修改对象的内部表示。
returning Collections.emptyList();
而不是 returning new ArrayList<Cheese>(emptyList)
的优点是可以避免创建另一个对象。此外,Collections.emptyList();
表示不可变的 List
.
cheesesInStock
列表可以在以后进行结构修改,但是 Collections.emptyList()
returns 是一个空列表,以后不能进行结构修改。Collections.emptyList()
returns EmptyList
,一些函数是:-
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}
我正在阅读 J. Bloch 的有效 Java,现在我在关于避免 returning null
s,但 returning 空集合的部分.这是该部分的代码示例:
// The right way to return a copy of a collection
public List<Cheese> getCheeseList() {
if (cheesesInStock.isEmpty())
return Collections.emptyList(); // Always returns same list
else
return new ArrayList<Cheese>(cheesesInStock);
}
我真的无法理解如果 cheesesInStock.isEmpty()
只 returning cheesesInStock
有什么问题。为什么 return 预定义的 Collections.emptyList()
更好。如果我们 return cheesesInStock
相反,我们可能会遇到什么样的麻烦。
如果方法 returns cheesesInStock
- 调用者可能会向列表中添加一些奶酪。
这是一种不好的做法,因为您可能想要控制添加过程。
因为
- 您将使用具有单例模式的
Collections.emptyList();
节省资源。 - 它是类型安全的
- 列表是不可变的(无法修改)
还可以 look at the API 你可以找到:
Returns the empty list (immutable). This list is serializable.
This example illustrates the type-safe way to obtain an empty list:
List<String> s = Collections.emptyList();
Implementation note: Implementations of this method need not create a separate List object for each call. Using this method is likely to have comparable cost to using the like-named field. (Unlike this method, the field does not provide type safety.)
这里的想法更多是关于安全对象发布或共享,返回对可变列表的引用允许调用者改变原始列表,这通常是一个坏主意。如果列表或一般对象是不可变的,那么您不需要这样做,例如 String 是不可变的,因此共享它是安全的。
String getString(){
return someString; // no need to copy
}
共享可变状态有两个主要问题:
- 当事情可以从任何地方发生变异时,很难检查程序的正确性。
- 线程安全变得更加困难,因为它需要同步,这通常是困难且昂贵的。
如果您直接 return cheesesInStock
,您 return 引用了与您所反对的相同的 List
(而不是它);因此,获取此列表的人所做的任何更改都将反映在对象的内部表示中。示例:
List<Cheese> list = myObject.getCheeseList();
list.add(new Cheese()); // this also affects the list inside myObject
为防止出现这种情况,最好使用 return 列表副本而不是 new ArrayList<Cheese>(previousList)
。请注意,除了 return 创建新的 List
,您还可以 return 使用 Collections.unmodifiableList
的不可修改的 List
视图:这具有相同的目标 -防止调用代码修改对象的内部表示。
returning Collections.emptyList();
而不是 returning new ArrayList<Cheese>(emptyList)
的优点是可以避免创建另一个对象。此外,Collections.emptyList();
表示不可变的 List
.
cheesesInStock
列表可以在以后进行结构修改,但是 Collections.emptyList()
returns 是一个空列表,以后不能进行结构修改。Collections.emptyList()
returns EmptyList
,一些函数是:-
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}