1

我有一个MapKs 到Set<V>s 的类,用于几个不同V的 s。我想使用通用工厂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()

4

5 回答 5

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>(). 调用泛型类的构造函数时,必须指定构造函数的类型参数。无论何时调用泛型方法,都必须指定类型参数。通常,这些可以从方法结果的分配或方法的参数中推断出来,但并非总是如此。

然而,这不是演员表。强制转换总是在运行时执行类型检查。像我在这里展示的那样指定泛型类型在编译时有效。

于 2009-09-21T19:24:07.817 回答
0

你需要一个明确的分配:

for (K key : keySet) {
  Set<V> mySet = setFactory(20);
  map.put(key, mySet);
}

没有它,编译器就无法知道<V>

于 2009-09-21T18:40:02.460 回答
0

Apache Commons Collections提供了一个LazyMap,您可以在其中提供一个创建地图值的工厂对象。您可以提供一个工厂来创建您的设置值。

现在,Commons Collections 不使用泛型,但这里有一个泛型端口

我希望我正确地解释了你的问题——这相当令人困惑。

于 2009-09-21T18:43:40.923 回答
0

如果您绝对必须将其放在一行中,则可以在 put 中放置一个胡说八道的作业:

 Set<V> s = null;
 for (K key : keySet) map.put(key, s = setFactory());

但这个答案更多的是展示另一种方法,而不是实际上表明它是一种更好的方法。

于 2009-09-21T18:48:26.863 回答
0

Hrm,实际上这似乎有效:

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;
}

甚至让我摆脱了必须最初分配地图的烦恼。我想我需要在参数列表中添加一个工厂,如果我想真正能够覆盖该类。

于 2009-09-21T18:48:30.047 回答