MKo*_*Kod 11 java generics wildcard hashmap superclass
在处理面试问题时,我遇到了以下代码:
List<Object> list = new ArrayList();
Map<Object, ? super ArrayList> m = new HashMap<Object, ArrayList>();
m.put(1, new Object());
m.put(2, list);
Run Code Online (Sandbox Code Playgroud)
上面两个put方法都是抛出编译时错误.但是,当我添加m.put(3, new ArrayList());它时添加到map没有编译时错误.
我很清楚我可以添加new Object()一个值,HashMap因为map声明属于类型< ? super ArrayList>; 这意味着我可以补充一点,高于任何值ArrayList(即超级的ArrayList)和ArrayList下面反对过,但没有什么ArrayList.
这个特殊的概念在Kathy Sierra和Bert Bates的SCJP 6中写得非常好,基于该理论和实例,我认为它应该按照我的理解工作.有人可以帮我理解错误吗?
你误解了通配符的?含义.你可能有一个常见的误解:
它并不意味着你可以把任何类型的对象在地图这是一种类型,它的父类的ArrayList.
这意味着地图中的值属于某种类型的未知类型ArrayList.由于确切的类型是未知的,编译器将不允许您将除ArrayList自身之外的任何类型的值作为值添加到映射中 - 编译器没有足够的信息来检查您正在执行的操作是否是类型安全的.
假设这是允许的,那么你可以做这样的坏事:
Map<Object, ArrayList> m1 = new HashMap<Object, ArrayList>();
Map<Object, ? super ArrayList> m2 = m1;
// This should not be allowed, because m2 is really a HashMap<Object, ArrayList>
m2.put(1, new Object());
Run Code Online (Sandbox Code Playgroud)
类型? super ArrayList表示未知类型,其下限为ArrayList。例如,它可能是Object,但也可能是AbstractList或ArrayList。
编译器唯一可以确定的是,该值的类型虽然未知,但保证不会比 更具体,因此可以添加ArrayList任何属于ArrayList或 的子类的对象。ArrayList
另请记住:编译器仅按照声明的类型进行处理;它忽略分配的类型。
put(1, new Object())失败:显然,Object不在界限之内。
put(1, list)失败:该变量的类型为List,它可能包含对 a 的引用LinkedList,但该引用不在所需的范围内。