2011-03-21 121 views
5

搜索了一阵后,我仍然找不到任何回答我的问题,甚至还有几个相关主题泛型的,所以在这里你去:上的Java泛型约束通配符

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? 

为什么最后两行不会编译?特别是最后一行。我对这个主题做了很多测试,但仍然无法理解这个逻辑。

谢谢。

回答

8

ArrayList<? super IOException>可能是下列任何一种(因为通配符):

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

代码需要与所有四种可能性工作。

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

下面是我没有得到:为什么这一个编译------ >>> list.add(新的FileNotFoundException(“这是好的。”)); < < < ----我觉得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!"); 
+0

@凯这有助于清楚地回答你的问题。 – asgs 2011-03-21 08:47:51

+0

谢谢,汤姆,这里是我没有得到:为什么这一个编译------ >>> list.add(新的FileNotFoundException(“这是好的。”)); <<< ----我认为FileNotFoundException也低于IOException的边界。但它编译好。 – 2011-03-21 08:52:51

+0

经过一段时间的摘要后,终于明白了:)即使在line1之后,list = new ArrayList (),但是list的元素的基类仍然被限制在满足条件“?super IOException”的类中,换句话说,元素的基类需要至少(或子类)IOException。 – 2011-03-21 09:14:21

1

Exception是超级类别IOException延伸Exception。你可以使用:

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

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

+0

是的,我知道,但我仍然需要了解问题的原因。不管怎么说:) – 2011-03-21 08:41:52

+1

对不起,但是这并不回答我的问题:(。 – 2011-03-21 08:46:05

+0

我的意思是第一行的有效性(列表的定义是有效的),以及编译器失败最后两行的逻辑是什么line? – 2011-03-21 08:47:34

0

我想是因为最后一个异常不从基类派生IOException异常

+0

我认为恰恰相反:因为'super'表示任何“IOException基于”的类应该是有效的,例如'Exception'或'Object',但似乎这只对第一行是正确的,但是( – 2011-03-21 08:39:36

4

考虑的list相同的声明,但有不同的任务:

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

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

+0

)你可能会更具体吗?请详细说明一下,我认为你是了解我的问题的核心人物,所以请给出更多的细节。 – 2011-03-21 08:45:15

+0

@Kai什么都不是,你得到了吗?它是引用的类型很重要吗?或者你不应该能够给'ArrayList '添加一个'Exception'?或者通常可能是对'ArrayList'的另一个引用与不同(但是正确)边界? – 2011-03-21 08:48:10

+0

或任何人都可以扩大这个答案更详细请,例如? – 2011-03-21 08:49:02

0

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

ClassCaseException和Exception不是从IOException派生的,因此它失败。

1

对我来说这是指较低的通配符通配符:<? super IOException>。上界有通配符将是<? extends IOException>

您示例中的通配符似乎只在分配给变量的新行Object的行中有效。后来访问时,显然不再有效。这就和ArrayList<IOException>一样。

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