我有一个static
List属性(例如ArrayList<String>
),它在多个方法之间传递以添加/修改元素。已经很少有方法,并且在不久的将来会有很多方法可以实现。
所以我需要确保没有方法可以清除列表。到目前为止,我已使用空方法体覆盖了clear()
方法。
我的方法如下:
private static List<String> singleList = new ArrayList<String>(){
@Override
public void clear() {
//here I disabled clear() with empty method
};
};
public static void main(String[] args) throws IOException {
addNumber(singleList);
addDigit(singleList);
addSign(singleList);
System.out.println(singleList);
}
private static void addNumber(List<String> singleList) {
singleList.add("1");
singleList.add("2");
}
private static void addDigit(List<String> singleList) {
singleList.add("A");
singleList.add("B");
singleList.clear();// Suppose, this line wrote accidentally, and I need to prevent it.
}
private static void addSign(List<String> singleList) {
singleList.add("+");
singleList.add("/");
}
还有更好的选择吗?
请建议我。
答案 0 :(得分:3)
为此,您可以使用不变性。 而不是改变列表,只返回一个具有您想要的元素的不可变的列表。例如,您可以使用Guava ImmutableList,创建构建器并添加上一个列表和/或新元素。
Guava docs关于clear
方法:
保证抛出异常并保持集合不被修改。
答案 1 :(得分:2)
我会添加UnsupportedOperationException
以确保调用clear()
的代码得到纠正。
如果代码依赖clear()
工作,则不应该使用该集合。
如果代码不需要clear()
,则不应该调用它。
答案 2 :(得分:2)
比扩展 ArrayList
更好的方法 - 虽然更详细 - 是撰写 ArrayList
一个类,以防止清除。
基本上,创建一个实现List
的类,并将其所有方法调用委托给另一个List
实例,而不是clear
:
final class CannotClearList<E> implements List<E> {
private final List<E> delegate;
CannotClearList(List<E> delegate) {
this.delegate = delegate;
}
@Override public boolean add(E element) {
return delegate.add(element);
}
@Override public E get(int i) {
return delegate.get(i);
}
@Override public void clear() {
// Cannot "do nothing": that violates the definition of the
// Collection.clear() method.
throw new UnsupportedOperationException();
}
// etc, for all other methods.
}
除了你现在不能限制你无法清除的ArrayList
(你可以重用它,例如LinkedList
)的优势之外,这样做的真正好处在于:为了防止clear()
工作,您还必须阻止List.subList
返回的列表让clear()
调用它们。
如果您通过扩展clear()
阻止了ArrayList
,那么您需要创建另一个类,该类也会阻止子列表中的clear()
。但是,使用上面的CannotClearList
,您只需将子列表包装在另一个CannotClearList
:
@Override public List<E> subList(int from, int to) {
return new CannotClearList<>(delegate.subList(from, to));
}
请注意,clear()
不是清除列表的唯一方法。你也可以:
remove
; Iterator
或ListIterator
并在迭代时致电remove()
; retainAll(Collection<?>)
作为参数。您应该仔细考虑是否也想要防止这些情况。
答案 3 :(得分:0)
您可以创建自己的UnClearableList
扩展ArrayList
- 然后在UnClearableList
中覆盖clear()
方法并在其中不执行任何操作(或者可能会抛出异常,具体取决于在你的设计上)。
然后在你处于“我想允许添加/删除但不清楚我的列表”的情况下使用UnClearableList。
您的做法在技术上是正确的。使用特殊的UnClearableList执行此操作可让您在其他类中重用它。 如果这只是一次学校练习,那就没有必要了。
答案 4 :(得分:0)
创建新类型或重载现有类型(如您所做)是常用的方法。此外,接口List
明确允许禁用clear
,因为它是可选操作。
来自JavaDoc:
/**
* Removes all of the elements from this list (optional operation).
* The list will be empty after this call returns.
*
* @throws UnsupportedOperationException if the <tt>clear</tt> operation
* is not supported by this list
*/
void clear();