黑马程序员技术交流社区

标题: 为什么编译器不允许创建类型变量的数组? [打印本页]

作者: 郑彬    时间: 2012-8-18 10:02
标题: 为什么编译器不允许创建类型变量的数组?
为什么编译器不允许创建类型变量的数组?即在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句有错误:
  Vector<Integer> vectorList[] = new Vector<Integer>[10];

作者: 黑马连家华    时间: 2012-8-18 12:25
你把泛型限定去掉试试
然后再试试普通Integer[] 加泛型
作者: 郑彬    时间: 2012-8-19 16:31
为什么编译器不允许创建类型变量的数组?这个谁知道呢?
作者: 郑彬    时间: 2012-8-19 23:28
求解释,谁知道呢?要是没人知道我就不问了,以后学深了在自己想吧。
作者: 童兴龙    时间: 2012-8-20 08:28
数组能够协变而泛型不能协变,不能实例化泛型类型的数组(new List<String>[3]是不合法的),除非类型参数是一个未绑定的通配符(new List<?>[3]是合法的)。

虽然将集合看作是数组的抽象会有所帮助,但是数组还有一些集合不具备的特殊性质。Java 语言中的数组是协变的(covariant),也就是说,如果 Integer扩展了 Number(事实也是如此),那么不仅 Integer是 Number,而且 Integer[]也是 Number[],在要求 Number[]的地方完全可以传递或者赋予 Integer[]。(更正式地说,如果 Number是 Integer的超类型,那么 Number[]也是 Integer[]的超类型)。您也许认为这一原理同样适用于泛型类型 —— List<Number>是 List<Integer>的超类型,那么可以在需要 List<Number>的地方传递 List<Integer>。不幸的是,情况并非如此。
不允许这样做有一个很充分的理由:这样做将破坏要提供的类型安全泛型。如果能够将 List<Integer>赋给 List<Number>。
那么下面的代码就允许将非 Integer的内容放入 List<Integer>:你知道泛型<>一旦指定那么就只能放该类型的数据。不能像数组那样可以放父类型数据。
1 List<Integer> li = new ArrayList<Integer>();
2 List<Number> ln = li; // illegal
3 ln.add(new Float(3.1415));


作者: 李知伦    时间: 2012-8-20 09:21
java中是不支持建立参数化类型数组的。
虽然在逻辑上来看应该是可以建立的。但是,我们得注意一件事:java的泛型和C++的泛型不一样,就像张老师在视频里说的,java的泛型是伪泛型,java的泛型只存在于编译时期!
然后我们在说说数组,数组和集合很相似,但是数组是建立以后就不可以改变的,数组中允许存入同一种类型的对象。虚拟机在将对象存入数组的时候会进行运行是检查,以确保存入的对象和运行时的类型相兼容。

如果在泛型中使用数组,这样的检查就显得不那么足够了,因为泛型只在编译时期有效,在运行时期java虚拟机读取不到原来的泛型信息,就因为这个原因就造成了一个类型安全的问题,所以java设计人员避免用户创建参数化的数组。
如果我们假设泛型化的数组可以创建:
ArrayList<String>[] al = new ArrayList[10];
ArrayList<Integer> in  = new ArrayList<Integer>();
in.add(12);
Object[] objs = al;//数组特性;
objs[0]= in;//不会报错
String ss = al[0].get(0);//java.lang.Integer cannot be cast to java.lang.String
这就是一个严重的类型安全问题,如果我们没有取出元素,而仅仅是存入,那么我们定义存入的是String但是却实际出入Integer;
作者: 郑彬    时间: 2012-8-20 23:31
问题暂时已经解决




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2