標籤:string 傳回值 log put turn lis code arraylist return
- 直接建立泛型數組不能通過編譯,而轉型對象數組通過編譯但是不能在JVM運行
- 問題在於數組將跟蹤他們的實際類型,而這個類型是在數組被建立時確定的,因此,即使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 泛型 泛型數組