对于几个不同的Map
,我有K
到Set<V>
s V
的课程。我想使用通用工厂ala:
protected static <T> Set<T> SetFactory(int size) {
return new HashSet<T>(size);
}
做类似
的事情for (K key : keySet) map.put(key, SetFactory());
并使通用部分工作(我收到编译错误,Set<Object>
和Set<V>
之间的类型不匹配),就像Set<V> x = SetFactory();
是否有将Class<V>
参数传递给SetFactory()
的替代方法?
答案 0 :(得分:2)
我真的不明白你的问题。这是你在找什么?
class MyClass {
protected static <T> Set<T> SetFactory(int size)
{
return new HashSet<T>(size);
}
protected static <K, V> Map<K, Set<V>> mapFactory(Collection<K> keys)
{
Map<K, Set<V>> result = new HashMap<K, Set<V>>(keys.size());
for (K key : keys)
result.put(key, MyClass.<V>SetFactory(20));
return result;
}
}
请注意泛型方法调用的显式类型参数(<V>
)。
更新
我可能错了,但在那里说 没有演员对我来说似乎是语义 - 不得不把MyClass。在前面似乎非常接近必须 投。你能解释一下这个区别吗?
强制转换为(Set<V>) SetFactory(20)
,它会生成有关类型安全性的编译器警告,因为对于类型擦除,无法检查SetFactory
的结果的运行时类型函数的类型为V
。
在方法调用上使用类型参数很像说new HashSet<V>()
。调用泛型类的构造函数时,必须指定构造函数的类型参数。无论何时调用泛型方法,都必须指定类型参数。通常,这些可以从方法结果的赋值或方法的参数中推断出来,但并非总是如此。
但是,它不是演员。强制转换总是在运行时执行类型检查。我在此处显示的指定泛型类型在编译时工作。
答案 1 :(得分:0)
您需要明确的作业:
for (K key : keySet) {
Set<V> mySet = setFactory(20);
map.put(key, mySet);
}
没有它,编译器就无法知道<V>
答案 2 :(得分:0)
Apache Commons Collections提供LazyMap,您可以在其中提供Factory对象,该对象可创建地图的值。您可以提供一个创建Set值的Factory。
现在,Commons Collections不使用泛型,但它有一个通用端口here。
我希望我能正确地解释你的问题 - 这很令人困惑。
答案 3 :(得分:0)
如果你绝对必须在一条线上,你可以在看跌期权中加入一个胡扯:
Set<V> s = null;
for (K key : keySet) map.put(key, s = setFactory());
但是,答案更多的是表明另一种方法,而不是实际上建议这是一种更好的方式。
答案 4 :(得分:0)
嗯,实际上这似乎有效:
protected static <K,V> Map<K,Set<V>> mapFactory(Collection<K> keys) {
Set<V> holder;
Map<K,Set<V>> result = new HashMap<K,Set<V>>(keys.size());
for (K key : keys) result.put(key, holder = SetFactory());
return result;
}
甚至让我摆脱了最初分配地图的烦恼。我想我需要在参数列表中添加一个工厂,如果我想实际上能够覆盖该类。