我正在阅读的一本关于Java的书告诉我,以下两段代码是等价的:
public <T extends Animal> void takeThing(ArrayList<T> list)
public void takeThing(ArrayList<? extends Animal> list);
在相反的页面上,我被告知后一段代码使用'?'作为通配符,意味着什么都不能添加到列表中。
这是否意味着如果我有一个列表(或其他集合类型?),我不能让它们同时接受多态参数并且可以重新调整大小?或者我只是误解了什么?
所有帮助/评论都表示赞赏,即使他们略微偏离主题。感谢。
答案 0 :(得分:2)
这是否意味着如果我有一个列表(或其他集合类型?),我不能让它们同时接受多态参数并且可以重新调整大小?
没有
这两段代码不是完全等价的。在第一行中,方法takeThing
具有类型参数T
。在第二行中,您使用的是通配符。
当您使用第一个版本时,您将指定T
将使用的具体类型。因为已知具体类型,所以添加到列表没有问题。
在第二个版本中,您只是说“list
是一个ArrayList
,其中包含一些扩展Animal
”的未知类型的对象。究竟是什么类型,不知道。您无法将对象添加到此类列表中,因为编译器没有足够的信息(它不知道实际类型是什么)来检查您是否应该允许添加到列表中的内容。
答案 1 :(得分:1)
通常情况下,如果在一个只接受列表而没有要添加的东西的方法中涉及添加到列表中,那么您将在其他地方使用Animal
并且您希望将其添加到列表。在这种情况下,必须声明您的方法,以便它接受的所有列表类型都允许在其中添加Animal
。这必须是List<Animal>
或Animal
的某些超类型的列表。它不可能是List<Dog>
- 您要添加的元素可以是Animal
。
这是下界和关键字super
的概念的来源。类型声明List<? super Animal>
匹配所有可接受的类型,如上所述。另一方面,您将无法以类型安全的方式从这样的列表中获取元素,因为它们通常可以是任何类型。如果方法想要添加和获取声明类型Animal
的元素,则它可以接受的唯一有效类型是List<Animal>
。