();
这段代码有什么问题?
t,tArray,list都是类变量,都是通过new声明了一个类型,看起来非常的相似.
但是这段代码是通不过的,因为编译期在编译时需要获得T类型,但是泛型在编译期类型已经被擦除了,所以new T()和new T[5] 都会报错,
但是你也许会认为,泛型类型可以擦除为顶级的Object类,那T类型擦除成Object不就可以编译了?
这样也不行,泛型只是Java语言的一部分,Java语言毕竟是一种强类型,编译型的安全语言,要确保运行期的稳定性和安全性就必须要求在编译器上严格检查.
但是为什么new ArrayList<T>()却不会报错呢?
这是因为ArrayList表面上是泛型,其实已经在编译期转型为了Object类型了,要看一下ArrayList的源代码就清楚了.
1 public class ArrayList<E> extends AbstractList<E>
2 implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
3 /**
4 * The array buffer into which the elements of the ArrayList are stored.
5 * The capacity of the ArrayList is the length of this array buffer.
6 */
7 private transient Object[] elementData;
8 /**
9 * Constructs an empty list with an initial capacity of ten.
10 */
11 public ArrayList() {
12 this(10);
13 }
15 /**
16 * Returns the element at the specified position in this list.
17 *
18 * @param index index of the element to return
19 * @return the element at the specified position in this list
20 * @throws IndexOutOfBoundsException {@inheritDoc}
21 */
22 public E get(int index) {
23 rangeCheck(index);
25 return elementData(index);
26 }
27 E elementData(int index) {
28 return (E) elementData[index];
29 }
注意看elementData定义,它容纳了ArrayList的所有元素,其类型是Object数组,因为Object是所有类的父类,数组又允许协变(Covariant),因此elementData数组可以容纳所有的实例对象.
元素加入时向上转型为Object类型(E类型转变为Object),取出时向下转型为E类型(Object转为E类型).
在某些情况下,我们确实需要泛型数组,怎么处理?
1 import java.lang.reflect.Array;
2 import java.util.ArrayList;
3 import java.util.List;
5 public class Client {
6 public static void main(String[] args) {
10 }
12 class Foo<T>{
13 //不再初始化,由构造函数初始化
14 private T t;
15 private T[] tArray;
16 private List<T> list= new ArrayList<T>();
17 //构造函数初始化
18 public Foo(){
19 try {
20 Class<?> tType = Class.forName("");
21 t = (T)tType.newInstance();
22 tArray = (T[])Array.newInstance(tType,5);
23 } catch (Exception e) {
24 e.printStackTrace();
25 }
27 }
此时运行就没有任何问题了,剩下的问题就是怎么在运行期获得T的类型.也就是tType参数.一般情况下泛型类型是无法获取的,不过在客户端调用时多传输一个T类型的class就会解决问题.
类的成员变量是在类初始化前初始化的,所以要求在初始化前它必须具有明确的类型.否则就只能声明,不能初始化.
本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/5624165.html,如需转载请自行联系原作者
【C 语言】数组 ( 数组本质 | 数组长度定义 | 数组初始化 | 编译时初始化 | 显式初始化 - 重置内存 )
【C 语言】数组 ( 数组本质 | 数组长度定义 | 数组初始化 | 编译时初始化 | 显式初始化 - 重置内存 )
【C++】函数 指针类型参数 与 引用类型参数 对比 ( 修改外部变量需要传入的参数要求 | 参数作返回值 )
【C++】函数 指针类型参数 与 引用类型参数 对比 ( 修改外部变量需要传入的参数要求 | 参数作返回值 )
【Flutter】Dart 数据类型 List 集合类型 ( 定义集合 | 初始化 | 泛型用法 | 初始化后添加元素 | 集合生成函数 | 集合遍历 )
【Flutter】Dart 数据类型 List 集合类型 ( 定义集合 | 初始化 | 泛型用法 | 初始化后添加元素 | 集合生成函数 | 集合遍历 )
问:把对象装数组分几步?
答:第一步把数组声明出来(new),第二步把对象装进去(=),第三步把数组遍历出来(for, for each)将编程看作是一门艺术,而不单单是个技术。
敲打的英文字符是我的黑白琴键,
思维图纸画出的是我编写的五线谱。
当美妙的华章响起,现实通往二进制的大门即将被打开。