我必须定义一个列表,它有两种可能的值
- 字符串
- 一些用户定义的类
我怎样才能创建一个类型安全的列表,因为它只接受这两种类型?
我想避免使用原始列表。
最佳答案
我不会声称这是一个完美的解决方案,但我会建议您使用“holder”类——一些作者(包括 Joshua Bloch,他表示标记类“冗长、容易出错且效率低下”)。
但是,鉴于您的情况,我看不到更好的方法。下面的解决方案提供:
- 插入没有可能共同祖先的类型时的编译时类型安全
- 无需实现和测试任何额外代码即可将当前列表替换为其他集合的能力
- 在其他上下文中使用 holder 类的能力
您可以像这样定义您的 holder 类:
class Holder { private String foo; private UserClass bar; boolean isString; boolean initialized=false; Holder (String str) { foo = str; isString=true; } Holder (UserClass bar) { this.bar = bar; isString=false; } String getStringVal () { if (! initialized) throw new IllegalStateException ("not initialized yet"); if (! isString) throw new IllegalStateException ("contents not string"); return foo; } // with a similar method for getUserClassVal() ... }
另一种选择是为标签使用 enum
,而不是 boolean 值 isString - 这具有易于扩展为其他类型的值(value)。
当然你会得到你的化合物列表:
List samsList = new ArrayList()
插入很容易,而且根据您的要求,编译时类型安全:
samsList.add (new Holder(stringVal)); samsList.add (new Holder(userClassVal));
从列表中检索值只是稍微复杂一点:在决定使用哪个 getter 之前,您必须检查标签 (holder.isString())。例如,列表上的 foreach 迭代看起来像这样:
for (Holder holder: samsList) { if (holder.isString()) doYourStringProcessing (holder.getStringVal()); else doYourUserClassProcessing (holder.getUserClassVal()); }
就像我说的,我并不是说这是完美的,但它满足您的要求将满足您的需求并最大限度地减少调用者的负担。
但是,我想指出,这对我来说似乎是考虑重构/重新设计某处的原因。我遵循的准则之一是,每当我发现自己为健全实践的异常(exception)辩护时,它值得更多思考,而不仅仅是“我该怎么做?”。
原因如下:假设我是正确的,在这种情况下异常(exception)是合理的,那么实际上只有两种可能性。一是声音实践不完整(因此“Prefer X over Y”应重写为“Prefer X over Y except in case Z”)。
但更有可能的是底层条款是一个不完美的设计,我们应该认真考虑进行一些重新设计/重构。
关于java - 如何制作一个可以接受两种不同的、不相关的类型的通用列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1351335/