java泛型数组初始化_[改善Java代码]不能初始化泛型参数和数组

本文介绍了Java中泛型在编译期的类型擦除特性,解释了为什么`new T()`和`new T[5]`会报错,而`new ArrayList<>()`不会。在编译时,由于类型擦除,无法直接创建泛型对象或数组,但可以通过反射来实现。同时,文章展示了如何在运行时通过反射获取泛型类型并初始化成员变量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

泛型类型在编译期被擦除,我们在类初始化时将无法获得泛型的具体参数,比如这样的代码:

class Foo{//private T t =new T();//报错Cannot instantiate the type T//private T[] tArray= new T[5];//报错Cannot create a generic array of T

private List list= new ArrayList();

}

这段代码有什么问题?

t,tArray,list都是类变量,都是通过new声明了一个类型,看起来非常的相似.

但是这段代码是通不过的,因为编译期在编译时需要获得T类型,但是泛型在编译期类型已经被擦除了,所以new T()和new T[5] 都会报错,

但是你也许会认为,泛型类型可以擦除为顶级的Object类,那T类型擦除成Object不就可以编译了?

这样也不行,泛型只是Java语言的一部分,Java语言毕竟是一种强类型,编译型的安全语言,要确保运行期的稳定性和安全性就必须要求在编译器上严格检查.

但是为什么new ArrayList()却不会报错呢?

这是因为ArrayList表面上是泛型,其实已经在编译期转型为了Object类型了,要看一下ArrayList的源代码就清楚了.

1 public class ArrayList extends AbstractList

2 implements List, 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 transientObject[] elementData;8 /**

9 * Constructs an empty list with an initial capacity of ten.10 */

11 publicArrayList() {12 this(10);13 }14

15 /**

16 * Returns the element at the specified position in this list.17 *18 *@paramindex index of the element to return19 *@returnthe element at the specified position in this list20 *@throwsIndexOutOfBoundsException {@inheritDoc}21 */

22 public E get(intindex) {23 rangeCheck(index);24

25 returnelementData(index);26 }27 E elementData(intindex) {28 return(E) elementData[index];29 }30 }

注意看elementData定义,它容纳了ArrayList的所有元素,其类型是Object数组,因为Object是所有类的父类,数组又允许协变(Covariant),因此elementData数组可以容纳所有的实例对象.

元素加入时向上转型为Object类型(E类型转变为Object),取出时向下转型为E类型(Object转为E类型).

在某些情况下,我们确实需要泛型数组,怎么处理?

1 importjava.lang.reflect.Array;2 importjava.util.ArrayList;3 importjava.util.List;4

5 public classClient {6 public static voidmain(String[] args) {7

8

9 }10 }11

12 class Foo{13 //不再初始化,由构造函数初始化

14 privateT t;15 privateT[] tArray;16 private List list= new ArrayList();17 //构造函数初始化

18 publicFoo(){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 }26

27 }28 }

此时运行就没有任何问题了,剩下的问题就是怎么在运行期获得T的类型.也就是tType参数.一般情况下泛型类型是无法获取的,不过在客户端调用时多传输一个T类型的class就会解决问题.

类的成员变量是在类初始化前初始化的,所以要求在初始化前它必须具有明确的类型.否则就只能声明,不能初始化.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值