Java 泛型 泛型數組

來源:互聯網
上載者:User

標籤:string   傳回值   log   put   turn   lis   code   arraylist   return   

  • 直接建立泛型數組不能通過編譯,而轉型對象數組通過編譯但是不能在JVM運行
    • public class ArrayOfGeneric{    static Generic<Integer>[] gia;    @SupperssWarnings("unchecked")    public static void main(String[] args){        gia = (Generic<Integer>[])new Generic[100]; // 通過類型轉換匿名對象        //! gia[0] = new Object(); //編譯不通過,不能(直接)建立泛型數組執行個體    }}
    • 問題在於數組將跟蹤他們的實際類型,而這個類型是在數組被建立時確定的,因此,即使gia已經被轉型為Generic<Integer>[],但這個資訊只存在於編譯期(並且如果沒有@SuppressWarning("unchecked")註解,將得到這個轉型的警告)。在運行時,它仍舊是Object數組
    • 因此,成功建立泛型數組的唯一方式就是建立一個被擦出類型的新數組,然後對其轉型(而且是在運行時轉型)
      •  直接對整個數組強制轉型,在編譯時間依舊會被擦除掉類型!所以應該在運行時轉型,而這時最好的辦法就是使用一個泛型數組封裝器,維護一個原始類型的數組,通過數組入口方法進行元素編譯期的型別安全檢測(對應傳回值)和強制類型轉換(對於運行時不重要),從而保證型別安全。

 

    • 對整個數組強制轉型的例子(錯誤方法)
    • public class GenericArray<T> {    private T[] array;    @SupperessWarning("unchecked")    public GenericArray(int sz) {        array = (T[]) new Object[sz];    }    public void put(int index, T item) {        array[index] = item;    }    public T get(int index) { return array[index]; }    public T[] rep() { return array; } //應該在運行時出口做文章    public static void main (String[] args){        GenericArray<Integer> gai = new GenericArray<Integer>(10);        // Integer[] ia = gai.rep(); //ClassCastException        Object[] oa = gai.rep(); //只能返回對象數群組類型為Object[]
      • 實際的運行時對象數組是Object[],而實際的運行時數組對象可能是T類型。

 

    • 因此,應該在運行時,數組對象的出口做轉型輸出,入口方法在編譯期已實作類別型安全,所以出口方法可以放心強制類型轉換,保證成功。如下
      • public class GenericArray2<T> {    private Object[] array;  //維護Object[]類型數組    @SupperessWarning("unchecked")    public GenericArray2(int sz) {        array = new Object[sz];    }    public void put(int index, T item) {        array[index] = item;    }    public T get(int index) { return (T)array[index]; }//數組對象出口強轉    public T[] rep() { return (T[])array; } //運行時無論怎樣都是Object[]類型     public static void main (String[] args){        GenericArray<Integer> gai = new GenericArray<Integer>(10);        // Integer[] ia = gai.rep(); //依舊ClassCastException        Object[] oa = gai.rep(); //只能返回對象數群組類型為Object[]        gai.put(0,11);        System.out.println(gai.get(0)); // 11 ,出口成功轉型    }}

         

  •  通過反射在運行時構出實際類型為type[]的對象數組,避免了類型擦除,從而轉換成功,無ClassCastException
import java.lang.reflect.*; public class GenericArrayWithTypeToken<T> {    private T[] array;    @SuppressWarning("unchecked")    public GenericArrayWithTypeToken(Class<T> type, int sz) {        array = (T[]) Array.newInstance(type, sz);//通過反射在運行時構出實際類型為type[]的對象數組,避免了類型擦除,從而轉換成功,無ClassCastException    }    public void put(int index, T item){        array[index] = item;    }    public T get(int index) { return array[index]; }    public T[] rep() { return array; }  //能成功返回了~    public static void main(String[] args) {        GenericArrayWithTypeToken<Integer> gawtt = new GenericArrayWithTypeToken<>(Integer.class, 10);        Integer[] ia = gawtt.rep(); //能成功返回了!    }}

  • 結論
    • 不能(直接)建立泛型數組
    • 泛型數組實際的運行時對象數組只能是原始類型( T[]為Object[],Pair<T>[]為Pair[] ),而實際的運行時數組對象可能是T類型( 雖然運行時會擦除成原始類型 )
    • 一般解決方案:(泛型數組封裝器):使用ArrayList收集泛型數組對象的對象元素,如ArrayList<T>、ArrayList<Pair<String>>
      • 將獲得數組的行為,以及由泛型提供的編譯期的型別安全

Java 泛型 泛型數組

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.