Java 我的方法泛型参数有什么问题

Java 我的方法泛型参数有什么问题,java,android,Java,Android,我想用泛型映射填充列表,但我的代码无法编译。我已经为这个问题准备了最简单的例子。在上面有问题的几行评论中,我把下面几行产生的错误放在了一起 void populateList(List<? extends Map<String,?>> list) { list.clear(); HashMap<String, ?> map; map = new HashMap<String,String>(); //The met

我想用泛型映射填充列表,但我的代码无法编译。我已经为这个问题准备了最简单的例子。在上面有问题的几行评论中,我把下面几行产生的错误放在了一起

void populateList(List<? extends Map<String,?>> list) {
    list.clear();
    HashMap<String, ?>  map;
    map = new HashMap<String,String>();
    //The method put(String, capture#2-of ?) in the type HashMap<String,capture#2-of ?> is not applicable for the arguments (String, String)
    map.put("key", "value"); // this line does not compile
    // The method add(capture#3-of ? extends Map<String,?>) in the type List<capture#3-of ? extends Map<String,?>> is not applicable for the arguments (HashMap<String,capture#5-of ?>)
    list.add(map);      //This line does not compile
}
void populateList(列表>列表){
list.clear();
HashMap图;
map=新的HashMap();
//类型HashMap中的方法put(String,capture#2-of?)不适用于参数(String,String)
map.put(“key”、“value”);//此行不编译
//类型列表中的add(capture#3-of?extends Map)方法不适用于参数(HashMap)
list.add(map);//此行不编译
}
为什么会这样?有什么我不明白的吗

编辑1

根据下面的一个答案,他在其中指出?表示未知类型,而不是对象的后代。这是一个正确的观点。而且,在这个方法中,我知道进入map的类型,所以我相应地修改了我的简单代码

void populateList(List<? extends Map<String,?>> list) {
    list.clear();
    HashMap<String, String>  map;  //known types
    map = new HashMap<String,String>(); 
    map.put("key", "value"); // this line now compiles
    // The method add(capture#3-of ? extends Map<String,?>) in the type List<capture#3-of ? extends Map<String,?>> is not applicable for the arguments (HashMap<String,capture#5-of ?>)
    list.add(map);      //This line STILL does not compile. Why is that?
}
void populateList(列表>列表){
list.clear();
HashMap;//已知类型
map=新的HashMap();
map.put(“key”、“value”);//这一行现在可以编译了
//类型列表中的add(capture#3-of?extends Map)方法不适用于参数(HashMap)
list.add(map);//这一行仍然没有编译。为什么?
}
我问这个问题的原因是,android SDK的方法需要这样的列表,而且似乎无法填充这样的列表。你是怎么做到的?打字

编辑2

由于有几项建议要更改我的签名,我要补充一点,我不能这样做。基本上,我想填充SimpleExpandableListAdapter的列表

void test() {
    ExpandableListView expandableListView.setAdapter(new ArrayAdapterRetailStore(this, R.layout.list_item_retail_store, retailStores));

    List<? extends Map<String, ?>> groupData= new ArrayList<HashMap<String,String>>();
    populateGroup(groupData)
    // child data ommited for simplicity
    expandableListView.setAdapter(  new SimpleExpandableListAdapter(
            this,
            groupdata,
            R.layout.list_group,
            new String[] {"GroupKey"},
            new int[] {R.id.tvGroupText},
            childData,
            R.layout.list_item_child,
            new String[] {"ChildKey"},
            new int[] {R.id.tvChilText}));
}

// I want populateGroupData() to be generic
void populateGroupData(List<? extends Map<String,?>> groupData) {
    groupData.clear();
    HashMap<String,String>  map;
    map = new HashMap<String,String>();
    map.put("key", "value");
    groupData.add(map); // does not compile 
}
void测试(){
ExpandableListView ExpandableListView.setAdapter(新的ArrayAdapterRetailStore(this,R.layout.list_item_retail_store,retailStores));
List>groupData=new ArrayList();
populateGroup(groupData)
//为了简单起见,需要对子数据进行复制
setAdapter(新的SimpleExpandableListAdapter(
这
分组数据,
R.layout.list_组,
新字符串[]{“GroupKey”},
新的int[]{R.id.tvGroupText},
儿童数据,
R.layout.list\u item\u child,
新字符串[]{“ChildKey”},
新的int[]{R.id.tvChilText});
}
//我希望populateGroupData()是泛型的
作废populateGroupData(列表>groupData){
groupData.clear();
HashMap图;
map=新的HashMap();
地图放置(“键”、“值”);
groupData.add(map);//不编译
}
来自文档

当实际类型参数为?时,它表示某个未知类型。我们传递要添加的任何参数都必须是此未知类型的子类型。因为我们不知道那是什么类型,所以我们不能传递任何信息。唯一的异常是null,它是每种类型的成员

因此,您只能添加

list.add(空)


请阅读本教程,了解Java是类型安全的!至少在这一点上:)

这将实现以下目的:

HashMap<String, String> map = new HashMap<String,String>(); 
map.put("key", "value");
((List<Map<String,String>>)groupData).add(map);
HashMap map=newhashmap();
地图放置(“键”、“值”);
((列表)groupData)。添加(地图);

您无法编写
Map-Map=getMap(“abc”)不带强制转换
问题更多地与easymock以及expect和andReturn方法返回/预期的类型有关,我不熟悉这些类型。你可以写

Map<String, String> expected = new HashMap<String, String> ();
Map<?, ?> actual = getMap("someKey");
boolean ok = actual.equals(pageMaps);
//or in a junit like syntax
assertEquals(expected, actual);
Map expected=newhashmap();
Map-actual=getMap(“someKey”);
布尔ok=actual.equals(页面映射);
//或者使用类似junit的语法
资产质量(预期、实际);
不确定这是否能和你的嘲弄混为一谈。这可能会奏效:

EasyMock.expect((Map<String, String>) config.getMap("sillyMap")).andReturn(pageMaps);
EasyMock.expect((Map)config.getMap(“sillyMap”)).andReturn(pageMaps);
还请注意,不能使用通配符向泛型集合添加任何内容。因此:

Map<?, ?> map = ...
map.put(a, b);
Map=。。。
地图放置(a,b);

不会编译,除非a和b为空

//also works with void populateList(List<Map<String,?>> list) {
void populateList(List<? super Map<String,?>> list) {
    list.clear();
    Map<String, String>  map;
    map = new HashMap<String,String>();
    map.put("key", "value"); // this line now compiles
    list.add(map);      //This line compiles
}

@user3104537链接现在已添加到答案。别忘了标记解决问题的答案。如果可以更改方法签名,您可以使用强制转换添加地图。请参见我的答案()或查看pdem答案()。您好,请查看我的答案-您必须强制转换groupData。这仍然不是特定于Android的!谢谢你的回复。但是我的列表应该被限制为至少使用Map或其派生类键入。因此,您可以在不使用extends或super的情况下准确地传递
列表
,但我希望我的方法对Map的所有后代都是泛型的,而不仅仅是Map。映射实际上是一个接口。为什么不想要一个列表类型的映射,就像我在示例的第一行中所说的那样。。。void populateList(List List){
?你知道列表类型的映射可以包含一个HashMap(以及映射的每个实例)吗?它将是通用的,正如你所希望的那样。如果你愿意,我可以在我的帖子中添加一个例子来解释为什么它不能与extends一起工作。也许我找到了一个最好的解释方法:
List
List<? super Map<String,?>> list or simply List<Map<String,?>> list 
// => this ensure you that the list can contains a Map<String,?>.

Map<String, String>  map is a Map<String,?> 
// =>that can ber inserted to the list, so you  don't need any cast
void exampleWithExtends(List<? extends Map<String,?>> list) {

}
void exampleWithSuper(List<? super Map<String,?>> list) {

}

void funWithGenerics(){
    exampleWithExtends(new ArrayList<TreeMap<String,String>>());
    exampleWithExtends(new ArrayList<Map<String,?>>());//works in both cases
    //exampleWithExtends(new ArrayList<Object>()); /does not compile
    //exampleWithSuper(new ArrayList<TreeMap<String,String>>()); //does not compile
    exampleWithSuper(new ArrayList<Map<String,?>>());//works in both cases
    exampleWithSuper(new ArrayList<Object>());
}