我正在阅读J. Bloch的有效Java,现在我正在关于避免返回null
但返回空集合的部分。这是以下部分的代码示例:
// 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
返回cheesesInStock.isEmpty()
,我真的无法理解有什么问题。为什么返回预定义的Collections.emptyList()
会更好。如果我们返回cheesesInStock
,我们可能遇到什么样的麻烦。
答案 0 :(得分:7)
如果方法返回api
- 调用者可能会在列表中添加一些奶酪。
这可能是一种不好的做法,因为您可能想要控制添加程序。
答案 1 :(得分:5)
因为
Collections.emptyList();
来保存资源。 还可以找到look at the API:
返回空列表(不可变)。此列表是可序列化的。
此示例说明了获取空列表的类型安全方法:
List<String> s = Collections.emptyList();
实施说明:此方法的实现无需为每个调用创建单独的List对象。 使用此方法的成本可能与使用同名字段相当。 (与此方法不同,该字段不提供类型安全性。)
答案 2 :(得分:5)
这里的想法更多是关于安全对象发布或共享,返回对可变列表的引用允许调用者改变原始列表,这通常是一个坏主意。如果列表或对象一般是不可变的,那么你不需要这样做,例如String是不可变的,因此共享它是安全的。
String getString(){
return someString; // no need to copy
}
共享可变状态带来两个主要问题:
答案 3 :(得分:2)
如果直接返回cheesesInStock
,则会返回对您所对象所拥有的List
的引用(而不是其副本);因此,获取此列表的人所做的任何更改都将反映在对象的内部表示中。例如:
List<Cheese> list = myObject.getCheeseList();
list.add(new Cheese()); // this also affects the list inside myObject
为了避免这种情况,最好使用new ArrayList<Cheese>(previousList)
返回列表的副本。请注意,您可以使用Collections.unmodifiableList
返回List
的不可修改的视图,而不是返回新的List
:这具有相同的目标 - 阻止调用代码修改内部表示对象。
返回Collections.emptyList();
而不是返回new ArrayList<Cheese>(emptyList)
的好处是可以避免创建另一个对象。此外,Collections.emptyList();
代表不可变的List
。
答案 4 :(得分:2)
cheesesInStock
列表可以在以后进行结构修改,但Collections.emptyList()
返回一个空列表,以后不能对其进行结构修改。Collections.emptyList()
返回EmptyList
,其中一些函数是: -
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}