不能初始化泛型参数和数组

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

class Foo<T>{
 private T t =new T();
 private T[] tArray=new T[5];
 private List<T> list= new ArrayList<T>();
}

这段代码有什么问题呢? t、tArray、list都是类变量,都是通过new声明了一个类型, 看起来非常相似啊!但这段代码是编译通不过的,因为编译器在编译时需要获得T类型,但 泛型在编译期类型已经被擦除了,所以new T()和new T[5]都会报错(可能有读者疑惑了 : 泛型类型可以擦除为顶级类Object,那T类型擦除成Object不就可以编译了吗?这样也不 行,泛型只是Java语言的一部分,Java语言毕竟是一个强类型、编译型的安全语言,要确保运行期的稳定性和安全性就必须要求在编译器上严格检査)。可为什么new ArrayList<T>()却 不会报错呢?

这是因为ArrayList表面是泛型,其实已经在编译期转型为Object 了,我们来看一下 ArrayList的源代码就清楚了,代码如下:


public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
   //容纳元素的数组
   private transient Object[] elementData;
    //构造函数
    public ArrayList() { 
       this(10);
     }
   //获得一个元素
   public E get(int index) {
    RangeChecM (index);
  //返回前强制类型转换
    return (E) elementData[index];
}
}
注意elementData的定义,它容纳了 ArrayList的所有元素,其类型是Object数组,因为Object是所有类的父类,_数组又允许协变(Covariant),因此elementData数组可以容 纳所有的实例对象。元素加入时向上转型为Object类型(E类型转为Object),取出时向下 转型为E类型(Object转为E类型),如此处理而已。

在某些情况下,我们确实需要泛型数组,那该如何处理呢?代码如下:

 private T t;
  private T[] tArray;
  private List<T> list=new ArrayList<T>();
  
  public Foo() {
	try {
		Class<?> tType=Class.forName("");
		t=(T) tType.newInstance();
		tArray=(T[]) Array.newInstance(tType, 5);
	} catch (Exception e) {
		e.printStackTrace();
	}
}

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

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




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你是我的天晴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值