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

class Foo<T>{
//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<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{
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer.
*/
private transient Object[] elementData;
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this(10);
} /**
* Returns the element at the specified position in this list.
*
* @param index index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
rangeCheck(index); return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
}

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

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

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

 import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List; public class Client {
public static void main(String[] args) { }
} class Foo<T>{
//不再初始化,由构造函数初始化
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就会解决问题.

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

[改善Java代码]不能初始化泛型参数和数组的更多相关文章

  1. [改善Java代码]强制声明泛型的实际类型

    Arrays工具类有一个方法asList可以把一个变长参数或数组变成列表,但是它有一个缺点:它所生成的List长度是不可改变的,而这在我们的项目开发中很不方便. import java.util.Ar ...

  2. [改善Java代码]动态加载不适合数组

    上一个建议解释了为什么要使用forName,本建议就说说哪些地方不适合使用动态加载. 如果forName要加载一个类,那它必须是一个类------8中基本类型就排除在外.它们不是一个具体的类. 其次它 ...

  3. [改善Java代码]Java的泛型是类型擦除的

    泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...

  4. [改善Java代码]警惕泛型是不能协变和逆变的

    什么叫做协变(covariance)和逆变(contravariance)? 在变成语言的类型框架中,协变和逆变是指宽类型和窄类型在某种情况下(如参数,泛型,返回值)替换或交换的特性,简单的说,协变是 ...

  5. [改善Java代码]避免带有变长参数的方法重载

    建议4: 避免带有变长参数的方法重载 在项目和系统的开发中,为了提高方法的灵活度和可复用性,我们经常要传递不确定数量的参数到方法中,在Java 5之前常用的设计技巧就是把形参定义成Collection ...

  6. [改善Java代码]避开基本类型数组转换列表陷阱

    开发中经常用到Arrays和Collections这两个工具类. 在数组和列表之间进行切换.非常方便.但是也会遇到一些问题. 看代码: import java.util.Arrays; import ...

  7. [改善Java代码]严格限定泛型类型采用多重界限

    从哲学上来说,很难描述一个具体的人,你可以描述它的长相,性格,工作等,但是人都是有多重身份的,估计只有使用多个And(与操作)将所有的描述串联起来才能描述一个完整的人,人在不同的环境中角色也在不断的更 ...

  8. java代码的初始化过程研究

        刚刚在ITeye上看到一篇关于java代码初始化的文章,看到代码我试着推理了下结果,虽然是大学时代学的知识了,没想到还能做对.(看来自己大学时掌握的基础还算不错,(*^__^*) 嘻嘻……)但 ...

  9. [改善Java代码]asList方法产生的List对象不可更改

    上一个建议之处了asList方法在转换基本类型数组时候存在的问题,在看下asList方法返回的列表有何特殊的地方.看代码: import java.util.Arrays; import java.u ...

随机推荐

  1. Homework-10 the Enhanced Version

    经过一周对于JavaScript HTML语言等相关知识的学习,我终于基本完成了作业的要求,也是实现了我原先计划的第二部,推出了加强版的Homework-10 他由3个HTML组成,JS脚本直接选择嵌 ...

  2. work4

    任务概述 给出多条英文单词,找出一个包含所有单词的填字阵.并且对于该方阵有一定特殊要求: a)      Stage 1 Every phrase in the input file is cover ...

  3. Spring Data JPA教程, 第六部分: Sorting(未翻译)

    The fifth part of my Spring Data JPA tutorialdescribed how you can create advanced queries with Spri ...

  4. Unity3D之Mecanim动画系统学习笔记(五):Animator Controller

    简介 Animator Controller在Unity中是作为一种单独的配置文件存在的文件类型,其后缀为controller,Animator Controller包含了以下几种功能: 可以对多个动 ...

  5. jeewx的使用_02 解析微信服务器post过来的数据

    如果在微信公众号接入了第三方的URL,那么用户微信服务器的请求将会被推送到第三方的URL上面,那么该如何解析数据呢?下面来分析 找到MessageUtil.java 这个类中有一个parseXml的静 ...

  6. Android下结束进程的方法

    转自:http://www.cnblogs.com/crazypebble/archive/2011/04/05/2006213.html 最近在做一个类似与任务管理器的东西,里面有个功能,可以通过这 ...

  7. 【WinForm】使用NSIS发布程序

    简介 NSIS(Nullsoft Scriptable Install System)是一个开源的 Windows 系统下安装程序制作程序.它提供了安装.卸载.系统设置.文件解压缩等功能 使用 以下是 ...

  8. IT人才什么最重要

    做人最重要 做人最主要的一条就是尊重别人 不尊重别人,一般都是产生于自己认为自己别别人强,认为别人总是犯一些非常二的错误,于是就不自觉的通过言语.表情.反应等一些细节流露出来 这种人时间长了就会没人愿 ...

  9. 安卓Activity界面切换添加动画特效

    在Android 2.0之后有了overridePendingTransition() ,其中里面两个参数,一个是前一个activity的退出两一个activity的进入, @Override pub ...

  10. 【Android】利用服务Service创建标题栏通知

    创建标题栏通知的核心代码 public void CreateInform() { //定义一个PendingIntent,当用户点击通知时,跳转到某个Activity(也可以发送广播等) Inten ...