预期的不适用的参数(String,Map <string,object =“”>); actual(String,Map <string,list <?=“”>&gt;)</string,> </string,>

时间:2013-09-25 14:24:04

标签: java oop generics

我一直在用java编写MongoDB接口,最近遇到了这个代码障碍。

我打电话要插入一份文件:

insertMongoDocument(String testName, Map<String, Object> input)

我有相应的单元测试:

Writer.insertMongoDocument("TestName", testMap);

测试地图的格式为

protected static Map<String, List<?>> testMap;

为什么这是非法的论点?是Map<String, List<?>>还不是Map<String, Object>

3 个答案:

答案 0 :(得分:4)

在java中,类型必须与声明的完全匹配。这是

insertMongoDocument(String testName, Map<String, Object> input)

你无法用

来调用它
Map<String, List<?>> map;
insertMongoDocument("foo", map);

即使Map<String, List<?>>似乎应该是Map<String, Object>的实例,但事实并非如此。

这是仿制药似乎不遵循基本继承的另一种情况,即List<SubClass> List<SuperClass>的实例。

如果确实如此,则会导致此错误:

List<Integer> listI = new ArrayList<Integer>();
List<Number> listN = listI; // compile error, but let's assume OK
listN.add(1.2); // Adding a Double (which is a Number) to a list of Integer - oops!
Integer i = listI.get(0); // BOOM... ClassCastException!

该行

List<Number> listN = listI;

不允许现在应该是显而易见的原因,这基本上就是你所看到的:你不能像一个类那样强制转换泛型类型。

答案 1 :(得分:2)

您需要使用以下签名

insertMongoDocument(String testName, Map<String, ? extends Object> input)

原因是Java无法关联参数类型。它试图仅应用它所知道的规则。在原始签名中,它知道它可以接受Object的{​​{1}}的第二个类型参数,然后找到Map,这不是完全匹配,所以错误被返回。需要使用List<?>extend运算符来指定一组适用的类型,而不是完全匹配。

唯一的Jon Skeet对此主题有一个很好的解释:What is a difference between <? super E> and <? extends E>?

答案 2 :(得分:0)

因为如果它是合法的,你可以将它传递给像insertMongoDocument这样的方法,它可能会尝试调用会破坏类型安全的input.put("", new Anything())

此处可用于签名的最常用类型是insertMongoDocument( String s, Map< String, ? super List< ? > > )