[改善Java代码]不能初始化泛型参数和数组
2024-09-21 12:13:38
泛型类型在编译期被擦除,我们在类初始化时将无法获得泛型的具体参数,比如这样的代码:
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就会解决问题.
类的成员变量是在类初始化前初始化的,所以要求在初始化前它必须具有明确的类型.否则就只能声明,不能初始化.
最新文章
- 第一届山东省ACM——Balloons(java)
- RedHat/Centos修改root密码
- 阐述ArrayList、Vector、LinkedList的存储性能和特性?(转)
- Redhat Linux 修改主机名(HOSTNAME)
- C# .net中获取台式电脑中串口设备的名称
- SCN试验之一
- 【cs229-Lecture17】离散与维数灾难
- hdu City Game
- sun.misc.BASE64Encoder是内部专用 API, 可能会在未来发行版中删除
- oracle commit之后的数据回滚
- JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释
- Hbiernate关联排序问题
- UVa 727 - Equation
- Django(五)框架之模板继承和静态文件配置
- 【译】5. Java反射——方法
- embOS ARM and Cortex Library Object and Symbol List
- graalvm 简单试用
- day22-类的多态
- 第9月第6天 push pop动画 生成器模式(BUILDER)
- Leetcode 89
热门文章
- HDU 4882 ZCC Loves Codefires (贪心)
- C++ 中复杂的声明
- Codeforces Round #334 (Div. 2) D. Moodular Arithmetic 环的个数
- uoj #31. 【UR #2】猪猪侠再战括号序列 贪心
- hdu1428漫步校园( 最短路+BFS(优先队列)+记忆化搜索(DFS))
- mahout算法源码分析之Itembased Collaborative Filtering(三)RowSimilarityJob验证
- JNI 系统钩子
- mydumper原理5
- SparkGraphXTest.scala
- 为laravel分页样式制定class