如何创建ArrayList的不可变子类?ColorList实现技术咨询
改造ColorList为ArrayList的不可变子类方案
嘿,我来帮你搞定这个不可变ColorList的改造问题!要把继承自ArrayList<Color>的类改成不可变的,核心就是阻止任何外部对列表元素的修改操作,同时保留你需要的循环获取颜色的功能。下面是具体的改造步骤和完整代码:
核心改造思路
因为ArrayList本身是可变集合,继承它的子类默认会继承所有修改方法(比如add、remove、clear),所以我们需要:
- 重写所有能修改集合的方法,让它们抛出
UnsupportedOperationException(Java标准不可变集合的统一做法) - 确保实例初始化后,内部元素无法被修改
- 保留你需要的循环获取颜色的逻辑,同时保证线程安全(可选,根据你的使用场景调整)
完整改造代码
import java.awt.Color; import java.util.ArrayList; import java.util.Iterator; import java.util.ListIterator; @SuppressWarnings("serial") public final class ColorList extends ArrayList<Color> { private static int colorIndex = -1; // 初始化固定的颜色集合 private static final Color[] FIXED_COLORS = { Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN, Color.BLUE, Color.LIGHT_GRAY }; public ColorList() { // 一次性初始化所有颜色,后续不再允许修改 super(FIXED_COLORS.length); for (Color color : FIXED_COLORS) { super.add(color); } } // 实现循环获取颜色的核心方法 public synchronized Color getNextColor() { colorIndex = (colorIndex + 1) % this.size(); return this.get(colorIndex); } // -------------------------- // 重写所有修改方法,抛出不可修改异常 // -------------------------- @Override public boolean add(Color e) { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public void add(int index, Color element) { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public boolean addAll(java.util.Collection<? extends Color> c) { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public boolean addAll(int index, java.util.Collection<? extends Color> c) { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public void clear() { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public Color remove(int index) { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public boolean remove(Object o) { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public boolean removeAll(java.util.Collection<?> c) { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public boolean retainAll(java.util.Collection<?> c) { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public Color set(int index, Color element) { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public void replaceAll(java.util.function.UnaryOperator<Color> operator) { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public void sort(java.util.Comparator<? super Color> c) { throw new UnsupportedOperationException("ColorList is immutable"); } // -------------------------- // 重写迭代器,防止通过迭代器修改元素 // -------------------------- @Override public Iterator<Color> iterator() { return new ImmutableIterator(super.iterator()); } @Override public ListIterator<Color> listIterator() { return new ImmutableListIterator(super.listIterator()); } @Override public ListIterator<Color> listIterator(int index) { return new ImmutableListIterator(super.listIterator(index)); } // 不可变迭代器实现 private static class ImmutableIterator implements Iterator<Color> { private final Iterator<Color> delegate; public ImmutableIterator(Iterator<Color> delegate) { this.delegate = delegate; } @Override public boolean hasNext() { return delegate.hasNext(); } @Override public Color next() { return delegate.next(); } @Override public void remove() { throw new UnsupportedOperationException("ColorList is immutable"); } } // 不可变列表迭代器实现 private static class ImmutableListIterator implements ListIterator<Color> { private final ListIterator<Color> delegate; public ImmutableListIterator(ListIterator<Color> delegate) { this.delegate = delegate; } @Override public boolean hasNext() { return delegate.hasNext(); } @Override public Color next() { return delegate.next(); } @Override public boolean hasPrevious() { return delegate.hasPrevious(); } @Override public Color previous() { return delegate.previous(); } @Override public int nextIndex() { return delegate.nextIndex(); } @Override public int previousIndex() { return delegate.previousIndex(); } @Override public void remove() { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public void set(Color e) { throw new UnsupportedOperationException("ColorList is immutable"); } @Override public void add(Color e) { throw new UnsupportedOperationException("ColorList is immutable"); } } }
关键细节说明
- 初始化优化:把固定颜色放到一个静态数组里,构造方法里一次性添加到父类ArrayList中,避免后续修改。
- 线程安全的循环逻辑:给
getNextColor()加上synchronized关键字(如果你的应用是多线程场景的话),防止多个线程同时修改colorIndex导致顺序混乱。如果是单线程场景,可以去掉synchronized。 - 覆盖所有修改入口:不仅要覆盖
add、remove这些直接修改方法,还要覆盖迭代器的修改方法,因为外部可能通过迭代器来修改集合元素。 - final类:保持类为
final,防止子类重写我们的不可变逻辑。
补充建议(可选)
其实Java官方更推荐组合而非继承来实现不可变集合,因为继承ArrayList需要覆盖大量方法,容易遗漏。如果可以不继承ArrayList,你可以这样实现:
import java.awt.Color; import java.util.ArrayList; import java.util.Collections; import java.util.List; public final class ColorList { private static int colorIndex = -1; private final List<Color> immutableColors; public ColorList() { List<Color> tempList = new ArrayList<>(); tempList.add(Color.CYAN); tempList.add(Color.DARK_GRAY); tempList.add(Color.GRAY); tempList.add(Color.GREEN); tempList.add(Color.BLUE); tempList.add(Color.LIGHT_GRAY); immutableColors = Collections.unmodifiableList(tempList); } public synchronized Color getNextColor() { colorIndex = (colorIndex + 1) % immutableColors.size(); return immutableColors.get(colorIndex); } // 暴露需要的只读方法,比如get、size等 public Color get(int index) { return immutableColors.get(index); } public int size() { return immutableColors.size(); } }
这种方式更简洁,而且天然不可变,不需要自己覆盖一堆方法。不过如果你的场景必须继承ArrayList,那还是用第一种方案。
内容的提问来源于stack exchange,提问作者kernel_panic
相关产品推荐
相关产品推荐

