繁体   English   中英

Java泛型:使用参数化类型实例化数组:非法吗?

[英]Java Generics: Instantiating arrays with parameterized types: illegal?

这里我一定很困惑。

我到处都读到,在泛型中,参数化类型的数组是非法的。

来自AngelikaLanger的示例:

static void test() {  
  Pair<Integer,Integer>[] intPairArr = new Pair<Integer,Integer>[10] ; // error  
  addElements(intPairArr);   
  Pair<Integer,Integer> pair = intPairArr[1];  
  Integer i = pair.getFirst();  
  pair.setSecond(i);  
} 

朗格的名言(但我在其他任何地方读的都说同样的话):

编译器禁止创建其组件类型为具体参数化类型的数组,例如本例中的Pair。 我们在前面的条目中讨论了为什么编译器将Pair []视为非法是合理的。

到目前为止,还可以。

但是在我的代码中:

private MyEntry<E> [] elements = (MyEntry<E>[])new Object[capacity];  

我正是这样做的,它可以很好地编译(我使用eclipse),但是会收到类强制转换异常错误(对象不能强制转换为MyEntry):

我的问题是,为什么此行首先编译?

我认为编译器不允许这种实例化。

我在这里做错/不同吗?

更新:

在同一页面上,我为什么能够成功执行以下操作:

List<E> elements[] = (List<E>[])new LinkedList[capacity];  

并且没有运行时异常吗?

更新:

我读过的所有地方(自从被频繁引用以来,都提到过Langer)都说编译器不允许此声明(参数化类型的数组)。
我可以理解之后会发生什么。
我不明白为什么编译器不报告错误。
我不是在判断,而是在阅读的所有地方说,这不是编译的。
我在念东西吗?

更新:我看到一些与new零件中缺少参数有关的注释。
这也没有问题:

List<Entry<KeyType, ValueType>> table[] = (List<Entry<KeyType, ValueType>>[])new LinkedList[capacity];

在第一个示例中,实例化没有问题-这正是您要创建的内容:

new Object[capacity]

完全合法。 但是,当您尝试进行MyEntry<E>时,确实会遇到运行时异常,因为Object数组不是MyEntry<E>数组。 如果这些通用参数化的数组不存在,则可能会有一个强制转换声明会被编译器拒绝的观点,尽管这取决于擦除的顺序。无论如何,实例化本身就很好。

在第二个示例中,您将创建LinkedList的非泛型数组。 然后,将其分配给通用引用,该引用在运行时将被删除为List[] 这很好用(因为对或错,数组是协变的)。

我不确定为什么会遇到运行时异常。 跟打电话说没什么不同

List<E> = new LinkedList();

您会得到一些未经检查的警告,但是没有什么会阻止代码的编译或运行。

因为LinkedListList的实例。 但是Object 不是 MyEntry的实例。 同样,编译器不会检查是否可以将一个对象强制转换为另一个对象。 因为它是运行时操作。

您应该使用:

private MyEntry<E> [] elements = new MyEntry [capacity];

要么:

class SomeOtherEntry extends MyEntry {}

private MyEntry<E> [] elements = new SomeOtherEntry [capacity];

但不是:

class SomeOtherEntry extends MyEntry {}

private SomeOtherEntry <E> [] elements = new MyEntry [capacity];

更新:

List<Entry<KeyType, ValueType>> [] table = (List<Entry<KeyType,ValueType>> []) new Linked[capacity];

您已经完全误解了所读的内容。 具有参数化类型的数组的类型绝对没有错: MyEntry<E>[]HashMap<String,Integer>[][]或其他任何东西。 您可以随意拥有所有此类类型的变量,并在可以使用任何类型的地方使用它们。

但是,使用数组创建时,您无法执行new MyEntry<E>[...] 该语言不允许这样做(出于类型安全的原因,我们将不在此处介绍),因此它是编译错误。

最好的解决方案是new MyEntry[] (原始类型的数组)或new MyEntry<?>[] (通配符类型的数组); 语言允许任何一种。 他们两个都需要您显式地转换回MyEntry<E>[]

由于您询问的是代码示例,因此您的第一个示例在语法上是正确的( new Object[...]没错,并且在语法上也可以MyEntry<E>[]转换为MyEntry<E>[] ),因此没有编译错误。 但是, MyEntry[]类型MyEntry[]的运行时检查在运行时失败,因为对象的实际类型Object[]不是MyEntry[]的子类型。

第二个代码示例在语法上也是正确的,并且强制转换的运行时检查成功( LinkedList[] List[]的子类型)。

暂无
暂无

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

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