首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >parameterized :用参数化类型实例化数组:非法?

parameterized :用参数化类型实例化数组:非法?
EN

Stack Overflow用户
提问于 2012-02-09 16:23:19
回答 4查看 7.2K关注 0票数 2

我在这里一定很困惑。

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

来自AngelikaLanger的示例:

代码语言:javascript
复制
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[]限定为非法是合理的。

到目前为止还好。

但在我的代码里:

代码语言:javascript
复制
private MyEntry<E> [] elements = (MyEntry<E>[])new Object[capacity];  

我就是这样做的,它编译得很好(我使用eclipse),但是得到了类强制转换异常错误(不能将对象转换为MyEntry):

我的问题是,为什么这一行首先要编译?

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

我在这里做错了什么?

更新:

在同一页上,为什么我能够成功地:

代码语言:javascript
复制
List<E> elements[] = (List<E>[])new LinkedList[capacity];  

并且没有运行时异常,

更新:

我读过的任何地方(因为兰格经常被引用)都说这个声明(参数化类型数组)是编译器不允许的。

我能理解在那之后发生了什么。

我不明白为什么编译器不报告错误。

我不是在评判,我是说我读到的每一个地方,它都说这不编译。

我是不是弄错了什么东西?

更新:--我看到了与new部件中缺少的参数有关的一些注释。

这也有问题:

代码语言:javascript
复制
List<Entry<KeyType, ValueType>> table[] = (List<Entry<KeyType, ValueType>>[])new LinkedList[capacity];
EN

回答 4

Stack Overflow用户

发布于 2012-02-09 16:30:59

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

代码语言:javascript
复制
new Object[capacity]

完全合法。但是,在尝试转换时确实会得到运行时异常,因为Object数组不是MyEntry<E>数组。如果这些泛型参数化数组不存在,那么编译可能会拒绝强制转换或声明,尽管这取决于删除的顺序。在任何情况下,实例化本身都很好。

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

我不知道您为什么要期待运行时异常;这与调用(比方说)没有多大区别

代码语言:javascript
复制
List<E> = new LinkedList();

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

票数 2
EN

Stack Overflow用户

发布于 2012-02-09 16:28:23

因为LinkedListList的一个实例。但是Object而不是,是MyEntry的一个实例。此外,编译器不检查一个对象是否可以转换为另一个对象。因为它是运行时操作。

你应该使用:

代码语言:javascript
复制
private MyEntry<E> [] elements = new MyEntry [capacity];

或者:

代码语言:javascript
复制
class SomeOtherEntry extends MyEntry {}

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

但不是:

代码语言:javascript
复制
class SomeOtherEntry extends MyEntry {}

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

更新:

代码语言:javascript
复制
List<Entry<KeyType, ValueType>> [] table = (List<Entry<KeyType,ValueType>> []) new Linked[capacity];
票数 1
EN

Stack Overflow用户

发布于 2012-02-09 23:28:36

无论你读到什么,你都完全误解了。拥有参数化类型的数组:MyEntry<E>[]HashMap<String,Integer>[][]之类的类型是绝对没有错的。您可以拥有所有您想要的此类类型的变量,并在可以使用类型的任何地方使用它们。

但是,通过创建数组,您不能执行类似于new MyEntry<E>[...]的操作。语言不允许这样做(出于类型安全的原因,我们不会在这里讨论),所以这是一个编译错误。

最好的解决方案是new MyEntry[] (原始类型数组)或new MyEntry<?>[] (通配符类型数组);语言允许这两种方法。这两种方法都需要您执行显式的MyEntry<E>[]转换。

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

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9214678

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档