我一直在用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>
?
答案 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< ? > > )
。