【发布时间】:2018-05-05 13:05:21
【问题描述】:
我正在设计一个简单的子类ArrayList<Color>。在我的应用程序上下文中,此列表充当“参考列表”,按照循环和明确定义的顺序返回 Color 对象。
@SuppressWarnings("serial")
public final class ColorList extends ArrayList<Color> {
private static int colorIndex = -1;
public ColorList() {
this.add(Color.CYAN);
this.add(Color.DARK_GRAY);
this.add(Color.GRAY);
this.add(Color.GREEN);
this.add(Color.BLUE);
this.add(Color.LIGHT_GRAY);
this.add(Color.MAGENTA);
this.add(Color.ORANGE);
this.add(Color.PINK);
this.add(Color.RED);
this.add(Color.YELLOW);
}
//if the color chosen is not the last one, increment index and get it.
public Color getNextColor() {
Color color = null;
if(colorIndex != this.size() - 1) {
color = this.get(++colorIndex);
}
else {
colorIndex = -1;
color = this.get(++colorIndex);
}
return color;
}
出于这个原因,我想让这个类不可变,因为它旨在成为一个只读列表,其内容在对象第一次实例化时定义,并在其整个生命周期内保持不变。同时,我需要能够利用 getNextColor() 来保持“循环”方式。
采取的方法
-
返回一个不可修改的引用。
public static List<Color> getInstance(){ return Collections.unmodifiableList(new ColorList()); }这种方法的问题在于,通过返回一个 List 引用它 阻止我调用
getNextColor()方法,使我的课程毫无用处。 强制转换并不能解决问题,因为底层对象是UnmodifiableRandomAccessList的实例,不能转换为ColorList。 -
覆盖引用可选操作的方法
@Override public boolean add(Color c) { throw new UnsupportedOperationException("color list is read-only"); } <overridding other methods such as addAll, remove...>如documentation 中所述,某些标记为“可选”的操作可能会或可能不会实现,具体取决于集合的目的。但这会阻止我首先添加颜色,就像我在实例化对象时在构造函数中所做的那样。
我想我可能误解了一些关键的设计方面。有没有办法让我的类不可变,而不限制它的(已经是基本的)功能?
编辑:为了向后兼容,这个类需要显式扩展 ArrayList。因此我不能使用包装类,尽管我也认为这将是最正确的方法。
【问题讨论】:
-
是否需要实现
List?您希望如何使用ColorList?如果不需要列表功能,也许可以避免复杂性...... -
为什么不直接使用
Collections.unmodifiableList(Arrays.asList(Color.CYAN, Color.DARK_GRAY, ...))? -
@ErnestKiwele 需要扩展 ArrayList
-
如果你必须扩展
ArrayList,它是可变的,那么你唯一的选择是覆盖改变状态的方法(你的帖子中的选项2)。 附带说明:您的colorIndex字段可能是您的“不变性”实现中的一个弱点。 -
我能想到另一种选择:覆盖
iterator()方法并提供您自己的Iterator<Color>实现,它总是为hasNext返回true并具有index字段。这样,您将从ColorList中删除可变状态并将其放入您的 Iterable 类中,您将在每次调用colorIterator.iterator()时创建一个实例。
标签: java arraylist collections immutability