我有一个Java类,它包含扩展MyClass的对象的子项。
1 2 3
| class MyClass {
List<? extends MyClass> items;
[...] |
由于某些原因,我无法将MyClass项插入此列表。我不明白为什么,也不知道如何绕过这个问题。例如:
1 2 3 4
| void foo(){
items = new LinkedList<MyClass>(); // This is OK
items.add(new MyClass()); // Not allowed... why?
} |
编译器说"方法添加(捕获1-of?"扩展类型列表中的MyClass)不适用于参数(MyClass)""
我真的不明白如何绕过这个问题,以及为什么编译器应该只接受一个必须扩展MyClass的类型。
注:为什么我需要使用这种方法?因为我需要允许MyClass的扩展具有子项列表。
- 为什么第一行是Myclass,而不是Myclass?
- 如果您只想将MyClass的任何子级的实例添加到项中,那么实际上并不需要? extends位:list将接受MyClass类型的任何实例或从MyClass继承的任何类…
- 我认为符号 extends MyClass>被理解为"扩展myclass的某个类,或者myclass本身"——但是在该类型中没有足够的信息让编译器知道您打算使用哪个myclass子类型……
List extends MyClass> items表示类型参数为未知类型,可分配给MyClass使用。
例如,它可以是MySubClass的List:
1 2 3
| public MySubClass extends MyClass{}
List<? extends MyClass> items = new ArrayList<MySubClass>(); |
现在考虑您的MyAnotherSubClass也从MyClass延伸出来:
1 2 3
| public MyAnotherSubClass extends MyClass{}
MyClass item = new MyAnotherSubClass(); // refer it using MyClass |
显然,不应允许List含有MyAnotherSubClass:
1
| items.add(item); // compile error |
宣言
1
| List<? extends MyClass> items; |
表示items是一个List,其类型参数不完全已知,而是MyClass或子类。
仔细阅读。它解释了向这样一个List中添加任何内容是不安全的类型:它的类型参数未知。如果恰好是MySubClass1,那么添加MyClass或MySubClass2是不正确的。如果恰好是MySubClass2,那么添加MySubClass1是不正确的。根本没有可以安全添加的类型。
如果你想要一个List,你可以添加MyClass类型的对象,也可以添加MyClass任何子类的对象,那么你可能只是在寻找List。
从技术上讲,List super MyClass>也可以用于特定目的,但您会遇到与此相反的问题:假定list元素是比Object更具体的类型是不安全的。
使用extends只能从集合中获得。你不能放进去。你可以用super来实现。
因此,在您的情况下,如果使用-List super MyClass> items;,您将不会得到任何编译/运行时错误。
虽然super同时允许get和put,但get时的返回类型是? super T。
- 真的!就是这样!我尝试的其他方法都有其缺点:使用List extends MyClass>,我不能添加任何内容。使用List,我需要在getter上投射所有元素,实际上我不能使用任何setter。这样我只需要在get上投射元素,这样就可以编写,即List super MyClass> _items = getItems(); if (_items == null) _items = new LinkedList(); MyClass item = (MyClass)_items.get(0);和items.add(new MyClass());谢谢。
- 乐于助人: