列出<interface> vs List <! - ?扩展了接口 - >在java </interface>中

时间:2014-08-18 10:58:57

标签: java generics collections arraylist

List<interfaceI>List<? extends InterfaceI>的Arraylist都有实现interfaceI的类对象。那什么时候应该用?

3 个答案:

答案 0 :(得分:9)

假设FooBar是实现InterfaceI的两个类。

第二个(List<? extends InterfaceI>)不允许向列表中添加任何内容(null除外),因为列表包含的类型是未知的:它可以是List<Foo>或{{ 1}}:你只是不知道。

因此,当您希望方法读取作为参数传递的列表元素并希望调用者能够使用List<Bar>List<InterfaceI>List<Foo>。使用List<Bar>作为参数只接受List<InterfaceI>类型的列表。

让我们举一个具体的例子:你想要计算一个数字列表的最大双精度值。这种方法不需要在列表中添加或设置任何内容。它只是迭代元素,获取每个数字并计算它们的最大值。签名可以是

List<InterfaceI>

但是,你将无法做到

 public double max(List<Number> list);

调用此方法的唯一方法是执行

List<Integer> ints = new ArrayList<>();
max(ints);

而如果您将方法声明为

List<Number> ints = new ArrayList<>();
max(ints);

然后你可以做

public double max(List<? extends Number> list);

答案 1 :(得分:1)

不同之处在于,如果您将列表声明为List<? extends S> myList,则myList变量可以按任意类型的列表S进行扩展,因此下面显示的关联将起作用:

public class Clazz implements S{}
List<? extends S> myList = new List<Clazz>(); // its fine as Clazz extends S
List<? extends S> myList = new List<S>(); // its fine as well
List<? extends S> myList = new List<Object>(); // ooooops it wil not work

但在这种情况下,您不会向PUT任何内容查找此类列表,因为您无法保证分配给myList

的列表实现所保留的对象的确切类型

如果您声明List<S> myList,那么您可以从列表中PUTGET个对象,因为您确定其中的内容,但是上面的分配将无效!< / p>

public class Clazz implements S{}
List<S> myList = new List<Clazz>(); // no way! 
List<S> myList = new List<S>(); //thats perfectly fine! - You can PUT new S in it;
List<S> myList = new List<Object>(); //known result;

答案 2 :(得分:0)

代替这个

public double max(List<? extends Number> list){

如果你喜欢 -

public List myList(List<? extends String> list){
list.add("string");// No, can not add anything in list except null
list.add(null);
}