带有上边界通配符的Java泛型

时间:2016-03-23 13:59:19

标签: java generics wildcard

我正准备参加Oracle认证专家Java SE 8考试,我在泛型和通配符方面遇到了一些问题。我很清楚,我提交的代码并没有多大意义,也不会以这种方式写在现实生活中。但对我来说这是一个练习。

  1. 第一行:Action编译
  2. 这个怎么编译? ((ArrayList<Exception>)exceptions).add(new Exception());是包含exceptions个对象(或子类)的ArrayList。如何将FileNotFoundException添加到Exception,假设只包含ArrayList子类的元素?如果没有演员表,那么这行不会编译。但即使使用强制转换,异常仍然无法包含FileNotFoundException的超类。我是对的,还是我误解了什么?

    1. 第2行:FileNotFoundException 没有编译
    2. 第1行和第2行之间的区别在于我现在转换为((ArrayList<IOException>)exceptions).add(new Exception());,而不是IOException。例外情况太广泛了。当然,要投降到Exception。这应该是这一行(第5行相同)不编译的原因。正确?

      1. 第3行:IOException
      2. 编译,我不明白为什么。基本上与第1行相同的问题((ArrayList<IOException>)exceptions).add(new IOException());IOException的超类,我怎样才能在这个FileNotFoundException中加入超类的成员?

        1. 第4行:ArrayList
        2. 编译。与第1行相同的问题。

          ((ArrayList<Exception>)exceptions).add(new FileNotFoundException());

2 个答案:

答案 0 :(得分:1)

这就是为什么你会得到一个不安全的演员&#34;编译器警告 - 因为它不安全。

你所有问题的答案都很糟糕:

  1. 当您投射列表时,它被视为该调用的类型
  2. 在将错误的类型放入列表时,您不会获得异常,但是当您将该对象从列表中取出并将其分配给列表类型的变量时,您将获得ClassCastException

答案 1 :(得分:0)

将泛型类型转换为&#34;泛型超类型&#34;编译因为运行时列表只是一个包含对象的列表,这些对象在运行时被检查为类型Exception(因为它被强制转换为);在运行时期间,ArrayList<FileNotFoundException>ArrayList<Exception>之间没有区别,并且强制转换会覆盖正常的类型检查行为。因此,不像C ++模板,ArrayList<FileNotFoundException>所持有的引用实际上并不是&#34;无法&#34;引用Exception个实例,因为在运行时它们只是通用的&#34; Object&#34;引用(双关语)。

List<? extends Throwable>表示&#34;某种Throwable的列表,但我不确定究竟是什么&#34;:因此,使用{{1}初始化引用} object是有效的但在现实生活中并不是非常有用:它意味着你不能在列表中添加任何 ,因为你失去了#34;编译时允许包含的类型。

另一方面,如果您希望能够声明&#34;此列表包含ArrayList<FileNotFoundException>或其某些父类型&#34;,您可以定义FileNotFoundException泛型类型。因此,ArrayList<? super FileNotFoundException>有效且允许您添加ArrayList<? super FileNotFoundException> exceptions = new ArrayList<IOException>();FileNotFoundException,但不允许IOException