所以我正在查看一些Java代码,然后偶然发现了:
List<? extends SomeObject> l;
基本上,此列表接受所有类型为SomeObject的对象- SomeObject本身或其子类。但根据多态性,它的子类也可以被视为SomeObject,因此这也可以起作用:
List<SomeObject> l;
那么既然第二种选项已经清晰明确且几乎相同,为什么有人会使用第一种选项呢?
所以我正在查看一些Java代码,然后偶然发现了:
List<? extends SomeObject> l;
基本上,此列表接受所有类型为SomeObject的对象- SomeObject本身或其子类。但根据多态性,它的子类也可以被视为SomeObject,因此这也可以起作用:
List<SomeObject> l;
那么既然第二种选项已经清晰明确且几乎相同,为什么有人会使用第一种选项呢?
List<SomeObject> l;
在这种情况下,你不能说 List<SomeObject> l = new ArrayList<SubClassOfSomeObjectClass>;
(不允许),而是要写为 。List<? extends SomeObject> l;
你可以这样说:
List<? extends SomeObject> l = new ArrayList<SubClassOfSomeObject>;
(允许的)
但请注意,在 List<? extends SomeObject> l = new ArrayList<SubClassOfSomeObject>;
中,你不能向列表l中添加任何内容,因为 ? 代表未知的类(当然可以添加 null 元素)。
更新:对于您在评论中提出的问题“如果我不能向列表中添加任何内容,我可能会做什么?"
现在考虑这样一种情况,你需要编写一个函数来打印你的列表,但它必须仅接受具有某些对象子类的 List。在这种情况下,如我之前所述,你无法使用
public void printList(List<SubClassOfSomeObjectClass> someList)
那么你会怎么做呢?你会做类似这样的事情:
public void printList(List<? extends SomeObject> someList) {
for(SomeObject myObj : someList) {
//process read operations on myObj
}
List<SomeObject>
与List<? extends SomeObject>
不同。请看下面的例子:
List<Object> x = new ArrayList<Object>();
List<String> y = new ArrayList<String>();
// x = y; Will throw Compilation exception
List<? extends Object> z = y; //will pass compilation
Collection<Object>
,在这种情况下,用户无法将他的字符串列表传递给您的方法。如果您接受 Collection<? extends Object>
,则用户可以传递他的 Collection<Apple>,Collection<Orange>
等,而不必显式创建另一个列表。List<? extends SomeObject> l;
不接受 new SomeObject()
, 但是 List<SomeObject> l;
可以。
以下也不起作用:
List<SomeObject> l = new ArrayList<SubTypeOfSomeObject>()
以下可以正常工作:
List<? extends SomeObject> l = new ArrayList<SubTypeOfSomeObject>()
X
即使可以转换为 Y
,也不能添加到 List<Y>
中。
因此,在您的第二种情况中,如果允许向 List<X> l;
添加 X 的子类,那么这将违反类型安全的基本原则。
作为第一个答案,
List<? extends SomeObject> l;
必须包含从SomeObject继承的对象,而不是直接使用SomeObject。