我想用通用映射填充List,但我的代码不能编译。我已经为这个问题准备了最简单的例子。在上面的注释中,有问题的行我将错误放在下面的行中。
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
}
为什么会这样?有什么我不明白的吗?
编辑1
根据下面的一个答案,他指出了?代表未知类型而不是Object的后代。这是一个有效的观点。而且,在方法内部我知道进入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?
}
我问这个的原因是因为android SDK的方法形式需要这样的列表,因为它似乎无法填充这样的列表。怎么做到这一点?强制转换?
编辑2
由于有几个改变我签名的提议,我会补充说我不能这样做。 Basicaly,我想填充SimpleExpandablaListAdapter的列表。
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
}
答案 0 :(得分:6)
来自文档
当实际类型参数为?时,它代表某种未知类型。我们传递给add的任何参数都必须是这种未知类型的子类型。由于我们不知道它是什么类型,我们无法传递任何内容。唯一的例外是null,它是每种类型的成员。
所以,你只能添加
list.add(null);
答案 1 :(得分:2)
这是工作代码
//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
}
以及它的工作原理:
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
编辑:
常见的错误是通配符&#34;?扩展Map&#34;将函数调用限制为&#34;至少&#34;键入地图。这不是你想要的,因为你可以传递List <
TreeMap <
字符串,?>>
例如不能包含HashMap。另外,您无法使用列表<
对象>
- &GT;为了说明泛型限制,我添加了2个带超级和扩展的例子
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>());
}
答案 2 :(得分:0)
Java是类型安全的!至少在这一点上:)
这样可以解决问题:
HashMap<String, String> map = new HashMap<String,String>();
map.put("key", "value");
((List<Map<String,String>>)groupData).add(map);
答案 3 :(得分:0)
没有演员表,你无法写Map<String, String> 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);
不确定这是否可以与你的嘲弄混合。这可能会奏效:
EasyMock.expect((Map<String, String>) config.getMap("sillyMap")).andReturn(pageMaps);
另请注意,您无法使用通配符向通用集合添加任何内容。所以这个:
Map<?, ?> map = ...
map.put(a, b);
不会编译,除非a和b为空