繁体   English   中英

带有上限通配符的 Java 泛型

[英]Java generics with upper bounded wildcards

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

  1. 第一行: ((ArrayList<Exception>)exceptions).add(new Exception()); 编译

这个怎么编译? exceptions是一个包含FileNotFoundException对象(或子类)的ArrayList 如何将Exception添加到ArrayList应该只包含FileNotFoundException子类的元素? 没有演员,该行就无法编译。 但即使使用强制转换,异常仍应无法包含FileNotFoundException超类。 我是对的还是我误解了什么?

  1. 第 2 行: ((ArrayList<IOException>)exceptions).add(new Exception()); 不编译

第 1 行和第 2 行之间的区别在于我现在转换为IOException ,而不是Exception 当然,异常太“宽”而无法转换为IOException 这应该是这一行(第 5 行相同)无法编译的原因。 对?

  1. 第 3 行: ((ArrayList<IOException>)exceptions).add(new IOException());

编译,我真的不明白为什么。 与第 1 行的问题基本相同。 IOExceptionFileNotFoundException超类,如何FileNotFoundException类的成员放入此ArrayList

  1. 第 4 行: ((ArrayList<Exception>)exceptions).add(new FileNotFoundException());

编译。 与第 1 行相同的问题。

package javaapplication;

import java.util.ArrayList;
import java.util.List;
import java.io.IOException;
import java.io.FileNotFoundException;

public static void main(String[] args) {
  List<? extends Throwable> exceptions = new ArrayList<FileNotFoundException>();

  ((ArrayList<Exception>)exceptions).add(new Exception());//1
  ((ArrayList<IOException>)exceptions).add(new Exception());//2,does not compile
  ((ArrayList<IOException>)exceptions).add(new IOException());//3
  ((ArrayList<Exception>)exceptions).add(new FileNotFoundException());//4
  ((ArrayList<FileNotFoundException>)exceptions).add(new
  Exception());//5,does not compile
}

这就是为什么您会收到“不安全强制转换”编译器警告的原因 - 因为它不安全。

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

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

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

List<? extends Throwable> List<? extends Throwable>表示“某种Throwable的列表,但我不太确定到底是什么”:因此,使用ArrayList<FileNotFoundException>对象初始化引用是有效的,但在现实生活中并不是非常有用:这意味着您可以不要向列表中添加任何内容因为您“丢失”了编译时间后允许包含的类型。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM