我在这里一定很困惑。
我到处读到,在泛型中,参数化类型数组是非法的。
来自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[]限定为非法是合理的。
到目前为止还好。
但在我的代码里:
private MyEntry<E> [] elements = (MyEntry<E>[])new Object[capacity]; 我就是这样做的,它编译得很好(我使用eclipse),但是得到了类强制转换异常错误(不能将对象转换为MyEntry):
我的问题是,为什么这一行首先要编译?
我认为编译器不允许这种实例化。
我在这里做错了什么?
更新:
在同一页上,为什么我能够成功地:
List<E> elements[] = (List<E>[])new LinkedList[capacity]; 并且没有运行时异常,
更新:
我读过的任何地方(因为兰格经常被引用)都说这个声明(参数化类型数组)是编译器不允许的。
我能理解在那之后发生了什么。
我不明白为什么编译器不报告错误。
我不是在评判,我是说我读到的每一个地方,它都说这不编译。
我是不是弄错了什么东西?
更新:--我看到了与new部件中缺少的参数有关的一些注释。
这也有无问题:
List<Entry<KeyType, ValueType>> table[] = (List<Entry<KeyType, ValueType>>[])new LinkedList[capacity];发布于 2012-02-09 16:30:59
在您的第一个示例中,实例化没有问题--以下是您要创建的内容:
new Object[capacity]完全合法。但是,在尝试转换时确实会得到运行时异常,因为Object数组不是MyEntry<E>数组。如果这些泛型参数化数组不存在,那么编译可能会拒绝强制转换或声明,尽管这取决于删除的顺序。在任何情况下,实例化本身都很好。
在第二个例子中,您正在创建一个非泛型的LinkedList数组。然后将其分配给一个泛化的引用,该引用在运行时将被擦除为一个List[]。这很好(因为无论对错,数组都是协变的)。
我不知道您为什么要期待运行时异常;这与调用(比方说)没有多大区别
List<E> = new LinkedList();您可能会得到一些未经检查的警告,但是没有什么可以阻止代码的编译或运行。
发布于 2012-02-09 16:28:23
因为LinkedList是List的一个实例。但是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];发布于 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[]的一个子类型)。
https://stackoverflow.com/questions/9214678
复制相似问题