Java泛型中的上限通配符

时间:2011-03-21 08:29:53

标签: java generics exception

在搜索了一段时间后,我仍然找不到任何问题的答案,即使有几个与泛型有关的话题,所以在这里你走了:

ArrayList<? super IOException> list = new ArrayList<Exception>();
list.add(new FileNotFoundException("this is ok."));
list.add(new IOException("This is ok"));
list.add(new ClassCastException("compile err"));//why compile err?
list.add(new Exception("compile err"));//why compile err? 

为什么最后两行不能编译?特别是最后一行。我一直在对这个话题进行相当多的测试,但仍然无法理解逻辑。

感谢。

6 个答案:

答案 0 :(得分:8)

ArrayList<? super IOException>可以是以下任何一种(因为有一张外卡):

ArrayList<IOException>
ArrayList<Exception>
ArrayList<Throwable>
ArrayList<Object>

代码需要处理所有四种可能性。

但如果是ArrayList<IOException>,则无法输入ClassCastExceptionException,因此编译错误。

  

这是我没有得到的:为什么这个编译------&gt;&gt;&gt; list.add(new FileNotFoundException(“this is ok。”)); &lt;&lt;&lt;&lt; ----我认为FileNotFoundException也低于IOException的界限。但它编译得很好。

不,FileNotFoundException没问题,因为它扩展了IOException,你可以把它放在所有四种类型的列表中。

请注意,由于历史原因,数组不会获得相同的严格类型检查,您可以编译以下内容(然后在运行时获取数组存储异常):

   Exception[] a = new IOException[4];
   a[0] = new FileNotFoundException("this is ok.");  
   a[1] = new IOException("This is ok");
   a[2] = new ClassCastException("compiles, but boom!");
   a[3] = new Exception("compiles, but boom!"); 

答案 1 :(得分:4)

考虑list的相同声明,但使用不同的作业:

ArrayList<? super IOException> list = new ArrayList<IOException>();

list的类型没有变化,但现在添加ClassCastExceptionException显然是错误的。

答案 2 :(得分:1)

Exception是超级类IOException 扩展 Exception。你可以使用:

 List<Exception> list = new ArrayList<Exception>();
 list.add(...); // any exception

然后它将编译所有异常类型。

答案 3 :(得分:1)

对我而言,这指的是较低的通配符:<? super IOException>。上限有界的通配符为<? extends IOException>

示例中的通配符似乎仅在将新Object分配给变量的行中有效。以后访问时,显然不再有效。然后它与ArrayList<IOException>相同。

所以你对自己的解释显然是错误的。上限和下限意味着它所说的。

答案 4 :(得分:0)

我认为因为异常的最后一个不是从基类IOException

派生的

答案 5 :(得分:0)

根据您的ArrayList引用泛型声明,您只能将实际的IOException(由于?super)或将IOException扩展到的对象添加到列表中。

ClassCaseException和Exception不是从IOException派生的,所以它失败了。