List<? extends Base> list
List<Base> list
两个声明之间有什么区别吗?
谢谢,
答案 0 :(得分:12)
是
List<Base>
可以包含所有来自Base
的不同内容的混合。 List<? extend Base>
包含同类项(从某种意义上说,它们必须全部来自某些特定的,未知类型,而这些类型又来自Base
)。
换句话说,List<? extends Base>
是List<T extends Base>
的基类。因此,您可以将List<T extends Base>
传递给任何需要List<? extends Base>
的方法。采用List<Base>
的方法也是如此。
答案 1 :(得分:6)
List<Base> list
可以包含Base
类型的元素或其任何子类型。 JDK类的一些示例:
List<Object> objects = new ArrayList<Object>();
objects.add(new Object()); // adding an Object instance
objects.add("I am a String"); // a String instance is also an Object
objects.add(Integer.valueOf(5)); // an Integer instance is also an Object
但是当你检索元素时,你只能将它们分配给Object
类的变量,因为Object
是声明列表的类型参数。
Object first = objects.get(1);
Object second = objects.get(2);
Object third = objects.get(3);
他们真正的运行时类仍然是Object
,String
和Integer
,因此您可以将它们转换为这些类型并使用它们,但是这样的强制转换可能会在运行时失败ClassCastException
如果做得不对,以这种方式处理列表通常不是一个好主意。
List<? extends Base> list
是一个实际上没有被指定用于声明变量的声明,因为正如Daniel Pryden的评论中已经提到的那样 - 你不能add()
其中的任何对象,只有null
s。< / p>
List<? extends String> list = new ArrayList<? extends String>();
list.add("a String")); // compile error!
但是您可以将这样的有界通配符表达式用于泛型方法参数。 List
本身的一个示例是addAll()
方法,其签名为:
boolean addAll(Collection<? extends E> c);
这使您可以执行以下操作:
List<String> strings = Arrays.asList("a", "b");
List<Object> objects = new ArrayList<Object>();
objects.addAll(strings);
如果没有<? extend E>
通配符,则无法将String
添加到List
Object
中,因为泛型类型(与数组不同)不是协变。这意味着List<String>
不是 List<Object>
的子类型。但是任何String
都是Object
,对吗?因此,有必要使用有界通配符声明方法参数 - List<String>
是<{1}}的子类型。
同样,我必须指出 - 有界通配符主要指定用于泛型方法参数,而不是方法返回类型或变量声明。