因類型擦除,執行期 T 變為 Object,new T[10] 實際為 new Object[10],強轉 (T[]) 會在執行期拋 ClassCastException。
Generic<Integer>[] arr = (Generic<Integer>[]) new Object[10]; // ClassCastException
class Holder<T> {
private Object[] arr;
public T get(int i) { return (T) arr[i]; } // OK
public T[] toArray() { return (T[]) arr; } // ClassCastException
}
rep() 回傳陣列會崩潰public class ArrayMaker<T> {
private final Class<T> type;
public ArrayMaker(Class<T> type) { this.type = type; }
@SuppressWarnings("unchecked")
public T[] createArray(int size) {
return (T[]) Array.newInstance(type, size); // 關鍵:執行期擁有真實型別
}
public List<T> createList() { return new ArrayList<>(); }
public static void main(String[] args) {
ArrayMaker<Type> am = new ArrayMaker<>(Type.class);
System.out.println(Arrays.toString(am.createArray(10))); // [type, type, ...]
System.out.println(am.createList());
}
}
class Type { @Override public String toString() { return "type"; } }
Array.newInstance(Class<?> componentType, int length) 為原生方法,直接在 JVM 層面分配指定元件型別的陣列T[],instanceof、getClass() 均正確@SuppressWarnings("unchecked") 抑制編譯器未檢查警告List<T> 無陣列擦除問題,API 豐富Class<T>Method.getGenericReturnType() 可獲取泛型資訊,配合型別權杖實現安全轉換// 編譯器會為 varargs 隱式建立陣列,同樣受擦除影響
// 安全做法:@SafeVarargs 抑制警告,且方法內不將陣列逸出
@SafeVarargs
public static <T> void safeVarargs(T... args) { ... }