如果我有异构集合,我确切知道我将要放置的类型是否有办法强制执行此操作。
例如,假设我有一个具有String键和值的映射,该映射可以是三个不相关的类型。现在我知道我只会放ClassA和ClassB或java.lang.String
例如这里是代码
public HetroCollection
{
public Map<String,Object> values;
}
public ClassA
{
}
public ClassB
{
}
public static void Main(String args[])
{
HetroCollection collection = new HetroCollection();
collection.values.add("first", new ClassA());
collections.values.add("second", new ClassB());
collections.values.add("third" , "someString");
//BAD want to stop random adds
collections.values.("fourth" , new SomeRandomClass());
}
我想到的选项是:
让类实现一个通用接口并在Map上使用Generics(问题是,如果这也涉及JDK或第三方的库类,那么更改类不是一个选项
隐藏地图并提供像
这样的方法put(String key,ClassA value); put(String key,ClassB value); put(String key,String value); get(String key);
重新思考设计而不是使用异构集合(不确定我将如何以其他方式表示)
寻找最佳实践答案。
答案 0 :(得分:2)
我认为“最佳实践”解决方案是您的第一和第三选择,只要情况允许。
你没有考虑的另一个选择是这样的:
public class MyMap extends HashMap<String, Object> {
...
// constructors
...
@Override
public void put(String key, Object value) {
if (value instanceof ClassA || value instanceof ClassB) {
super.put(key, value);
} else {
throw new IllegalArgumentException("Verbotten!");
}
}
...
}
您可以将其与第二个选项结合使用,以便存在静态类型选项,甚至可能将put(String, Object)
方法标记为已弃用以阻止其使用。
最后,可以选择忽略问题,并依赖应用程序员不要将随机内容放入地图中。根据具体情况,这甚至可能是最佳解决方案。
答案 1 :(得分:1)
嗯,你已经证明你首先想到的不是一个选择。如果你真的需要这个功能,第二个想法是最好的选择。否则最好的选择是重新考虑你的方法。但是,如果我们知道一点上下文,它会更容易帮助。
答案 2 :(得分:0)
这个被称为类的Java有一个很好的工具。举个例子,你可以这样写一个:
public class Foo {
private ClassA first;
private ClassB second;
private String someString;
...
public void setFirst(ClassA first) {
this.first = first;
}
public ClassA getFirst() {
return first;
}
...
}
说真的,鉴于你所说的这听起来就像你想要的那样。如果您只想允许特定键,其值可能只是特定类型(取决于键本身)......那就是class
。如果有一些非常强烈的理由让你需要在这里使用String
地图密钥(这对我来说似乎不太可能),请解释一下。
修改强>
当我回答这个问题时,由于某种原因,我需要强制执行仅映射到特定类型值的特定键。再看一遍,似乎情况可能并非如此。如果情况并非如此,我认为您最好的选择是重新考虑设计(举例说明您需要这样做的原因可能会有所帮助)。如果你这样做并且没有想出任何东西,我认为#2是最好的选择。它以某种类型安全的方式强制限制地图可以具有的值类型。
答案 3 :(得分:0)
还有第四种选择:
如果你想将这些类型的实例粘贴到一个集合中,很可能它们有一些共同之处。如果你不能引入一个通用的超类型来表达这种共性,你仍然可以引入一个具有这种公共超类的并行类层次结构,并声明你的地图可以保存那种类型的项目。
// You can find a better name ;-)
abstract class Foo {
public abstract void foo();
public void bar() {
// something generic
}
public abstract void visit(FooVisitor visitor);
}
class ClassAFoo {
final ClassA delegate;
// Constructor and implementations for foo()
}
class ClassBFoo {
final ClassB delegate;
// Constructor and implementations for foo()
}
class StringFoo {
final String delegate;
// Constructor and implementations for foo()
}
优点:
缺点:
答案 4 :(得分:0)
理论上,使用Functional Java中的HList可以实现List中混合对象的类型安全性。请参阅blog post和Examples。来自IBM developerworks的相关this article也是如此。我在理论上写道,因为在实践中,类型声明只能处理有限数量的元素,并且它会迅速增长。