正确使用集合实例工厂的泛型

时间:2017-06-06 13:20:18

标签: java generics factory apache-commons

我尝试使用Apache Commons Collections v4执行以下操作:

Map<Integer, List<String>> namesPerNumber = 
        MapUtils.lazyMap(
            new HashMap<Integer, List<String>>(), 
            FactoryUtils.instantiateFactory(ArrayList.class));

namesPerNumber.get(1).add("Mickey");

但是我在lazyMap调用时得到以下编译器错误:

  

MapUtils类型中的方法lazyMap(Map&lt; K,V&gt;,Factory&lt;?extends V&gt;)不适用于参数(HashMap&lt; Integer,List&lt; String&amp; t;&gt;,Factory&lt; ArrayList&gt;)

有没有正确的方法可以使用工厂在地图中生成列表?我也尝试了这个:

Map<Integer, List<String>> namesPerNumber = 
            MapUtils.lazyMap(
                new HashMap<Integer, List<String>>(), 
                FactoryUtils.<List<String>instantiateFactory(ArrayList.class));

但是我在instantiateFactory调用时得到了这个错误:

  

类型为FactoryUtils的参数化方法&lt; List&lt; String&gt;&gt; instantiateFactory(Class&lt; List&lt; String&gt;&gt;)不适用于参数(Class&lt; ArrayList&gt;)

我找到的唯一可行解决方案如下,但我发现它很难看:

Map<Integer, List<String>> namesPerNumber3 = 
            MapUtils.lazyMap(
                new HashMap<Integer, List<String>>(), 
                new Factory<List<String>>() {
                    @Override
                    public List<String> create() {
                        return new ArrayList<String>();
                    }
                });

任何帮助表示感谢。

签名,
lostingenerics

1 个答案:

答案 0 :(得分:3)

由于类型擦除,类文字仅支持可再生类型或原始类型,因此ArrayList.class表示原始类型ArrayList,而不是预期的ArrayList<String>

解决此问题的一种方法是使用一个未经检查的操作:

@SuppressWarnings("unchecked") Class<ArrayList<String>> type = (Class)ArrayList.class;

Map<Integer, List<String>> namesPerNumber = 
    MapUtils.lazyMap(
        new HashMap<Integer, List<String>>(), 
        FactoryUtils.instantiateFactory(type));

请注意,@SuppressWarnings("unchecked")的效果仅限于此处的单个未选中操作。

或者你使用

Map<Integer, List<String>> namesPerNumber = 
    MapUtils.lazyMap(
        new HashMap<Integer, List<String>>(), 
        FactoryUtils.prototypeFactory(new ArrayList<String>()));

代替。

如果您使用的是Java 8,最好的选择是

Map<Integer, List<String>> namesPerNumber = 
    MapUtils.lazyMap(new HashMap<>(), () -> new ArrayList<>());