博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[改善Java代码]不能初始化泛型参数和数组
阅读量:5865 次
发布时间:2019-06-19

本文共 2703 字,大约阅读时间需要 9 分钟。

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

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<T>()却不会报错呢?

这是因为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 transient Object[] elementData; 8 /** 9 * Constructs an empty list with an initial capacity of ten.10 */11 public ArrayList() {12 this(10);13 } 14 15 /**16 * Returns the element at the specified position in this list.17 *18 * @param index index of the element to return19 * @return the element at the specified position in this list20 * @throws IndexOutOfBoundsException {
@inheritDoc}21 */22 public E get(int index) {23 rangeCheck(index);24 25 return elementData(index);26 }27 E elementData(int index) {28 return (E) elementData[index];29 } 30 }

 

 注意看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; 4  5 public class Client { 6     public static void main(String[] args) { 7          8          9     }10 }11 12 class Foo
{13 //不再初始化,由构造函数初始化14 private T t;15 private T[] tArray;16 private List
list= new ArrayList
();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 }26 27 }28 }

 

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

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

 

转载地址:http://tsynx.baihongyu.com/

你可能感兴趣的文章
Android TabActivity使用方法
查看>>
java ShutdownHook介绍与使用
查看>>
Eclipse的 window-->preferences里面没有Android选项
查看>>
《麦田里的守望者》--[美]杰罗姆·大卫·塞林格
查看>>
遇到的那些坑
查看>>
央行下属的上海资信网络金融征信系统(NFCS)签约机构数量突破800家
查看>>
[转] Lazy evaluation
查看>>
常用查找算法总结
查看>>
grep 零宽断言
查看>>
被神话的大数据——从大数据(big data)到深度数据(deep data)思维转变
查看>>
修改校准申请遇到的问题
查看>>
【DL-CV】浅谈GoogLeNet(咕咕net)
查看>>
python大佬养成计划----win下对数据库的操作
查看>>
(cons '(〇 . 前言) 《为自己写本-Guile-书》)
查看>>
监控软件zabbix之安装
查看>>
No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=arm64, VALID_ARCHS=armv7 armv7s)
查看>>
Exchange Server 2016 独立部署/共存部署 (七)—— DAG功能测试
查看>>
对RTMP视频流进行BitmapData.draw()出错的解决办法
查看>>
Linux 进程中 Stop, Park, Freeze【转】
查看>>
Spark修炼之道(基础篇)——Linux大数据开发基础:第九节:Shell编程入门(一)...
查看>>