了解在java泛型中使用通配符?

时间:2014-09-25 19:36:03

标签: java generics wildcard

我问了一个类似的问题,这是一个更具体的版本,希望得到一个明确的答案。 在尝试理解Java通用类型和通配符#34;?"的用法时,我尝试了以下方法:

List<Integer> li4 = new ArrayList<Integer>();
  li4.add(new Integer(5));
  Integer myInt4 = li4.get(0);

现在我用更通用的类型取代&#39;

List<? extends Integer> li = new ArrayList<Integer>(); 
Integer myInt = li.get(0);

以上编辑很好。 似乎&#39; li&#39;上面被视为一个列表,其中每个元素都是一个整数(查看li.get(0)调用)。 我也可以做以下事情:

li = li4;

以上编译并运行正常。 但是当我尝试:

li.add(new Integer(5));

我遇到编译错误(使用Oracle JDeveloper作为IDE):

 Error(24,9):  cannot find method add(java.lang.Integer)

&#39 ;?扩展整数&#39;应该允许任何扩展Integer的类型。它的行为类似于&#39; get&#39;返回Integer的方法。类似地,当ArrayList被分配给它时它不会抱怨。因此,例如'li = new ArrayList<String>()'无法编译。那么为什么我可以分配另一个ArrayList<Integer>(),得到一个Integer但不添加整数?

2 个答案:

答案 0 :(得分:5)

? extends Integer 意味着&#34;应该允许任何扩展整数&#34;的类型。这意味着对于某些扩展为整数的特定 List<T>,这是T

所以你从List<? extends Integer>中获得的任何内容都会延长Integer,但你不能放任何东西 - 我们不知道你的类型是什么?重新投入比赛T

举一个具体的例子,Integer延伸Number。所以你可以写

List<? extends Number> list1 = new ArrayList<Integer>();
List<? extends Number> list2 = new ArrayList<Double>();

但是你不应该被允许写list2.add(new MyNumber())list2.add(new Integer(3)),因为list2实际上是List<Double>

答案 1 :(得分:0)

以下代码帮助我理解答案:

    List<Exception> exL = new ArrayList<Exception>();
    exL.add(new Exception());
    Exception ex = exL.get(0);
    Throwable th = exL.get(0);
    exL.add(new NullPointerException());
   /** Error(153,7):  cannot find method add(java.lang.Exception)
    exL.add(new Throwable());
   **/

因此,当我们声明List时,元素必须至少具有Exception行为,这意味着Exception,RuntimeException及其子类。可以将从这样的列表返回的元素分配给Exception或其任何子类。 &#34;例外e = exL.get(0)&#34;或者&#34; Throwable th = exL.get(0)&#34;。也可以添加Exception实例或向List说NullPointerException。

列出genExcepList,可以是列表,列表或列表为&#34;?延伸异常&#34;表示异常及其所有子类。实际上,List是List,List等的超类。对于这些列表类型中的任何一个,返回的元素来自&#39; get&#39;保证呼叫的类型为Exception。所以可以这样做:Exception e = genExcepList.get(0)。但是调用genExcepList.add(异常)是不行的,因为List必须满足它允许的每个类型的限制,包括List,List,List等。唯一有效的是genExcepList.add(null)as&#39;空&#39;适用于各种类型。 另一方面,如果我们有类似的东西: List rtgs = new ArrayList(); &#34 ;?超级例外&#34;表示异常及其任何超类。所以List代表List,List和List。在任何这些列表类型中,可以调用&#34; add(new Exception());&#34;所以可以调用rtgs.add(new Exception()),因为Exception也是一个Throwable和Object。但是,调用&#34; Exception ex = rtgs.get(0)&#34;因为从List返回的元素可以是Exception,Throwable和Object中的任何一个。所以唯一能安全工作的是&#34;对象ex = rtgs.get(0)&#34;。