[英]How to instance generic parameterized class
I just implement a MapBuilder
to build map easy, But when i try to get an instance of HashMap.class,I suddenly found that I can't use HashMap.class to get such an instance. 我只是实现了MapBuilder
来轻松构建地图,但是当我尝试获取HashMap.class的实例时,我突然发现我不能使用HashMap.class来获取这样的实例。
It's illegal! 这是非法的!
So can anybody tell me why and how to solve this problem? 所以有人能告诉我为什么以及如何解决这个问题?
The MapBuilder is follow: 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;
}
}
}
And the test code is below: 测试代码如下:
public static void main(String[] args) {
HashMap<String, String> v = start(HashMap<String,String>.class).put("a", "b").get();
System.out.println(v);
}
It's impossible to obtain a parameterized class type variable for a generic type, as Reimeus has said. 正如Reimeus所说,获取泛型类型的参数化类类型变量是不可能的。 So you have three choices. 所以你有三个选择。
First, you can live with the unchecked cast: 首先,您可以使用未经检查的演员:
Class<? extends Map<String, Integer>> clazz =
(Class<? extends Map<String, Integer>>) HashMap.class;
Second, you can reify the parameters for a class by extending it (in this example, using an anonymous inner class): 其次,可以通过(在该示例中使用匿名内部类)延伸它具体化的一类的参数:
Class<? extends Map<String, Integer>> clazz =
new HashMap<String, Integer>() {}.getClass();
Or third, and best, just take the Map
instance instead of a class in start()
. 或者第三,也是最好的,只需使用Map
实例而不是start()
中的类。 You're not saving the user any work by taking the Class
rather than an instance of Map
, and the first thing you do is create an instance of it. 您不是通过使用Class
而不是Map
的实例来保存用户的任何工作,而您要做的第一件事就是创建它的实例。
By passing it in, the user can even tweak the settings of the map (eg for a HashMap
, set the load factor, for TreeMap
, specify the Comparator
) so it's a better alternative anyway. 通过传入,用户甚至可以调整地图的设置(例如,对于HashMap
,为TreeMap
设置加载因子,指定Comparator
),因此无论如何它都是更好的选择。 If you need to, you can assert that it's empty when it's passed in. 如果需要,可以断言传入时它是空的。
If for some reason you really need a factory, don't use Class
: it doesn't work well as a factory, because the only way you can customize the instance that Class
creates is by subclassing the class and providing a new no-arg constructor. 如果由于某种原因你真的需要一个工厂,不要使用Class
:它不能很好地作为工厂,因为你可以自定义Class
创建的实例的唯一方法是通过继承类并提供一个新的no-arg构造函数。 Just create an interface Factory<T>
that has a method T create()
and then accept a Factory<? extends Map<K, V>
只需创建一个具有T create()
方法的接口Factory<T>
然后接受一个Factory<? extends Map<K, V>
Factory<? extends Map<K, V>
. Factory<? extends Map<K, V>
。
First since start
takes a class you would have to pass it an unparameterized class such as HashMap.class
. 首先,因为start
接受一个类你必须通过它的unparameterized类如HashMap.class
。 Second, as you're returning a generic type Map
, you would have to make your local type match also, so to use: 其次,当您返回泛型类型Map
,您还必须使本地类型匹配,因此要使用:
Map<String, String> v = start(HashMap.class).put("a", "b").get();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.