[英]How to instance generic parameterized class
我只是实现了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);
}
正如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
创建的实例的唯一方法是通过继承类并提供一个新的no-arg构造函数。 只需创建一个具有T create()
方法的接口Factory<T>
然后接受一个Factory<? extends Map<K, V>
Factory<? extends Map<K, V>
。
首先,因为start
接受一个类你必须通过它的unparameterized类如HashMap.class
。 其次,当您返回泛型类型Map
,您还必须使本地类型匹配,因此要使用:
Map<String, String> v = start(HashMap.class).put("a", "b").get();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.