将通用Class参数限制为实现Map的类

时间:2019-02-18 10:57:57

标签: java generics

我正在尝试编写一个request.getParameter("user_id"); 构建器。其中一个构造函数将允许客户端指定他们希望构建的Map的类型

Map

目的是应该可以使用以下方法构造构建器的实例:

public class MapBuilder<K, V> {

    private Map<K, V> map;

    /**
     * Create a Map builder
     * @param mapType the type of Map to build. This type must support a default constructor
     * @throws Exception
     */
    public MapBuilder(Class<? extends Map<K, V>> mapType) throws Exception {
        map = mapType.newInstance();
    }

    // remaining implementation omitted
}

MapBuilder<Integer, String> builder = new MapBuilder<Integer, String>(LinkedHashMap.class);

似乎构造函数参数的类型签名当前不支持此功能,因为上面的行会导致“无法解析构造函数”编译错误。

如何更改构造函数,使其仅接受实现MapBuilder<Integer, String> builder = new MapBuilder<Integer, String>(HashMap.class); 的类?

3 个答案:

答案 0 :(得分:10)

使用Supplier代替Class

public MapBuilder(Supplier<? extends Map<K, V>> supplier) {
    map = supplier.get();
}

然后可以这样称呼它:

MapBuilder<Integer, Integer> builder = new MapBuilder<>(LinkedHashMap::new);

这也更安全,因为Class<Map>可能没有默认构造函数,这会引发错误(这不是响应性很强的代码)

答案 1 :(得分:2)

以下将起作用:

public MapBuilder(Class<? extends Map> mapType) throws Exception {
    map = mapType.newInstance();
}

答案 2 :(得分:2)

问题是LinkedHashMap.class

Class<LinkedHashMap>

而不是类似

Class<LinkedHashMap<Integer, String>>

这些类型也是不可转换的类型(因此您无法进行转换),并且无法获取后者的实例。

您可以做的是将构造函数更改为

public MapBuilder(Class<? extends Map> mapType) throws Exception

泛型在运行时被删除,因此在运行时所有Map的行为都将与Map<Object, Object>一样。因此,您要构造的类使用原始类型都没关系。


不建议使用Class::newInstance。使用

mapType.getConstructor().newInstance()