List<interfaceI>
和List<? extends InterfaceI>
的Arraylist都有实现interfaceI的类对象。那什么时候应该用?
答案 0 :(得分:9)
假设Foo
和Bar
是实现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
,那么您可以从列表中PUT
和GET
个对象,因为您确定其中的内容,但是上面的分配将无效!< / 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);
}