2012-10-28 183 views
3

我只是实现了一个MapBuilder来建立地图容易, 但是,当我试图获得HashMap.class的一个实例,我突然发现我不能使用HashMap.class来获得这样一个实例。如何实例泛型参数化类

这是非法的!

那么有人可以告诉我为什么以及如何解决这个问题?

的MapBuilder是遵循:

import java.util.Map; 

public abstract class MapBuilder { 

    public static <K, V, T extends Map<K, V>> InnerMapBuilder<T, K, V> start(
      Class<T> clazz) { 
     return new InnerMapBuilder<>(clazz); 
    } 

    public static class InnerMapBuilder<T extends Map<K, V>, K, V> { 

     private T target; 

     public InnerMapBuilder(Class<T> clazz) { 
      try { 
       target = clazz.newInstance(); 
      } catch (InstantiationException | IllegalAccessException e) { 
       throw new RuntimeException(e); 
      } 
     } 

     public InnerMapBuilder<T, K, V> put(K key, V val) { 
      target.put(key, val); 
      return this; 
     } 

     public T get() { 
      return target; 
     } 
    } 
} 

而且测试代码如下:

public static void main(String[] args) { 
    HashMap<String, String> v = start(HashMap<String,String>.class).put("a", "b").get(); 
    System.out.println(v); 
} 

回答

1

这是不可能获得一个泛型类型参数化类类型的变量,如Reimeus说。所以你有三个选择。

首先,你可以与选中投过:

Class<? extends Map<String, Integer>> clazz = 
    (Class<? extends Map<String, Integer>>) HashMap.class; 

其次,你可以通过(在这个例子中使用匿名内部类)扩展它具体化一类的参数:

Class<? extends Map<String, Integer>> clazz = 
    new HashMap<String, Integer>() {}.getClass(); 

第三,也是最好的,只需要Map实例而不是start()中的类。您不是通过使用Class而不是Map的实例来保存用户的任何工作,并且首先要做的是创建它的一个实例。

通过使其在中,用户甚至可以调整地图的设置(例如,用于一个HashMap,设置负载因子,TreeMap,指定Comparator),所以它是一个更好的选择反正。如果需要,你可以断言它时,它的真实传递是空

如果由于某种原因,你真的需要一个工厂,不使用Class:它不作为工厂很好地工作,因为只有这样,您可以自定义Class创建的实例,方法是继承该类并提供新的无参数构造函数。只需创建一个接口Factory<T>,该接口有一个方法T create(),然后接受Factory<? extends Map<K, V>

+0

谢谢你的回答,我会花一些时间考虑你的话。 – jackalope

+0

使用第三种解决方案进行解决。 – jackalope

0

一是因为start需要一个类,你必须通过它的unparameterized类如HashMap.class。其次,你返回一个泛型类型Map,你必须让你的本地类型的比赛也,所以使用方法:

Map<String, String> v = start(HashMap.class).put("a", "b").get(); 
+0

谢谢,但这不应该是安全的,并会得到一些通用类型的警告 – jackalope

+0

是的,但你不能定义一个参数化的类类型变量。 – Reimeus