zoukankan      html  css  js  c++  java
  • [改善Java代码]不能初始化泛型参数和数组

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

    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的源代码就清楚了.

     1 public class ArrayList<E> extends AbstractList<E>
     2         implements List<E>, 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 return
    19      * @return the element at the specified position in this list
    20      * @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<T>{
    13     //不再初始化,由构造函数初始化
    14     private T t;
    15     private T[] tArray;
    16     private List<T> list= new ArrayList<T>();
    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就会解决问题.

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

  • 相关阅读:
    第二次作业循环语句
    c语言01次作业分支,顺序结构
    PAT 1027. Colors in Mars
    PAT 1026 Table Tennis
    PAT 1035 Password
    PAT 1038. Recover the Smallest Number
    PAT 1028 List Sorting (25)
    PAT 1041 Be Unique (20)
    PAT 1025 PAT Ranking
    1037. Magic Coupon
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/5624165.html
Copyright © 2011-2022 走看看