在Java Generics声明中使用'或'

时间:2010-06-02 15:42:13

标签: java generics collections

我有一个返回

实例的方法
Map<String, List<Foo>> x();

和另一个返回

实例的方法
Map<String, Collection<Foo>> y();

现在,如果我想在我的字段中动态添加其中一个地图,我该如何编写其中的泛型?

即:

public class Bar {
    private Map<String, ? extends Collection<Foo>> myMap;

    public void initializer() {
       if(notImportant) myMap = x(); //OK
       else myMap = y(); // !OK (Need cast to (Map<String, ? extends Collection<Foo>>)
    } 
}

即使将y()声明为Collection,我也可以转换为签名吗?

如果不能投射,我可以以某种方式写这个(集合或列表) 我的意思是,List是一个集合,所以它应该是可能的。

private Map<String, Collection<Foo> | List<Foo>>> myMap;

2 个答案:

答案 0 :(得分:4)

使用? extends Collection执行此操作的方式很好。你不能拥有像OR这样的东西,因为如果你做了myMap.get("someString"),你就不会知道你会得到什么。你不能做List|Collection someVariable = myMap.get("someString"),你必须选择一个,如果你选择收藏它就像使用? extends一样,如果你选择列表,你最终会遇到各种麻烦,如果map中的对象实际上是一个Set(也是一个集合),而不是一个列表,你尝试调用只有List的方法(比如indexOf)。至于您需要使用? extends的原因是因为Map<String, List>即使List扩展集合也不会扩展Map<String, Collection>

你应该注意,使用? extends Collection只会让你从地图中获取值,从那以后它确定你得到的是一个Collection(或Collection的子),但如果你试图把在地图中的某些内容,您将无法(因为myMap可能是Map<String, Set>,但由于您只将其视为Map<String, ? extends Collection>,因此您可能会尝试在其中放置一个不合适的列表)

答案 1 :(得分:3)

我不确定你的问题是什么。这段代码(基本上是你的代码)编译得很好。

import java.util.*;
public class Generic {
    static class Foo {};
    static Map<String, List<Foo>> x() {
        return null;
    }
    static Map<String, Collection<Foo>> y() {
        return null;
    }
    static Map<String, ? extends Collection<Foo>> myMap;
    public static void main(String[] args) {
        myMap = x();
        myMap = y();
        myMap = new HashMap<String,SortedSet<Foo>>();
        for (Collection<Foo> value : myMap.values());
    }
}

但是,您不能执行List<Integer|String>之类的操作。 Java泛型类型边界不起作用。