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

2 回答 2

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您要做的第一件事就是创建它的实例。

通过传入它,用户甚至可以调整地图的设置(例如,对于 a HashMap,设置负载因子,对于TreeMap,指定Comparator),因此无论如何它是一个更好的选择。如果需要,可以在传入时断言它为空。

如果出于某种原因您确实需要工厂,请不要使用Class: 它作为工厂效果不佳,因为您可以自定义Class创建的实例的唯一方法是子类化该类并提供新的无参数构造函数。只需创建一个Factory<T>具有方法的接口,T create()然后接受一个Factory<? extends Map<K, V>.

于 2012-10-28T15:39:46.320 回答
0

首先,由于start需要一个类,您必须将它传递给一个未参数化的类,例如HashMap.class. 其次,当您返回泛型类型Map时,您还必须使本地类型匹配,因此要使用:

Map<String, String> v = start(HashMap.class).put("a", "b").get();
于 2012-10-28T15:14:14.807 回答