泛型与数组
Java 不允许创建泛型数组,这是类型擦除带来的限制。
泛型数组限制
Java
// 错误:不能创建泛型数组
List<String>[] array = new List<String>[10]; // 编译错误
// 错误:不能创建类型参数数组
public class Box<T> {
private T[] array = new T[10]; // 编译错误
}
编译器禁止:泛型数组创建会导致类型安全问题。
类型安全问题
Java
// 假设允许创建泛型数组(演示问题)
List<String>[] stringLists = new List<String>[10]; // 假设允许
Object[] objects = stringLists; // 数组协变,允许
objects[0] = new ArrayList<Integer>(); // 放入 List<Integer>
String s = stringLists[0].get(0); // 取出 Integer,类型错误!
类型擦除后:
- List[] 擦除为 List[]
- 可放入任意 List 类型
- 读取时类型不一致导致错误
Java 编译器禁止创建泛型数组,避免这种运行时错误。
数组协变 vs 泛型不变
| 特性 | 数组 | 泛型 |
|---|---|---|
| 继承关系 | 协变(有继承) | 不变(无继承) |
| String[] | Object[] 子类 | - |
| List | 不是 List 子类 | 不变 |
| 类型检查 | 运行时 | 编译期 |
Java
// 数组协变(有继承关系)
String[] strings = new String[10];
Object[] objects = strings; // ✅ 允许(协变)
objects[0] = new Integer(1); // 运行时 ArrayStoreException
// 泛型不变(无继承关系)
List<String> stringList = new ArrayList<>();
List<Object> objectList = stringList; // ❌ 编译错误
替代方案
使用 List 替代数组
Java
// 推荐:使用 List 替代泛型数组
List<List<String>> list = new ArrayList<>();
// 添加元素
list.add(new ArrayList<>());
list.get(0).add("Hello");
使用 Object 数组 + 类型检查
Java
public class GenericArray<T> {
private Object[] array;
private int size;
public GenericArray(int capacity) {
array = new Object[capacity];
}
public void set(int index, T value) {
array[index] = value;
}
public T get(int index) {
return (T) array[index]; // 类型擦除后转型
}
}
使用反射创建数组
Java
public class GenericArray<T> {
private T[] array;
@SuppressWarnings("unchecked")
public GenericArray(Class<T> type, int capacity) {
array = (T[]) Array.newInstance(type, capacity);
}
public void set(int index, T value) {
array[index] = value;
}
public T get(int index) {
return array[index];
}
}
// 使用
GenericArray<String> arr = new GenericArray<>(String.class, 10);
arr.set(0, "Hello");
@SuppressWarnings("unchecked")
Java
// 转型警告抑制
@SuppressWarnings("unchecked")
List<String>[] array = (List<String>[]) new List[10];
// 或转型时抑制
@SuppressWarnings("unchecked")
T[] array = (T[]) new Object[10];
警告抑制说明:开发者明确知道转型安全时使用,谨慎使用。
允许的泛型数组声明
Java
// 声明泛型数组引用(不创建)
List<String>[] array; // ✅ 声明允许
// 创建原始类型数组
List[] rawArray = new List[10]; // ✅ 允许
List<String>[] array = (List<String>[]) rawArray; // 警告
// 方法参数接收泛型数组
public void method(List<String>[] array) {} // ✅ 允许
GenericArrayType
反射获取泛型数组类型:
Java
public class MyClass {
private List<String>[] array;
}
Field field = MyClass.class.getDeclaredField("array");
Type type = field.getGenericType();
if (type instanceof GenericArrayType) {
GenericArrayType gat = (GenericArrayType) type;
Type componentType = gat.getGenericComponentType(); // List<String>
}
要点总结
- 不能创建泛型数组:new List[10]
- 不能创建类型参数数组:new T[10]
- 原因:类型擦除后数组协变导致类型安全问题
- 数组协变,泛型不变
- 替代方案:List 替代数组、Object 数组转型、反射创建
- 声明泛型数组引用允许,创建不允许
- 转型时使用 @SuppressWarnings("unchecked") 抑制警告
📝 发现内容有误?点击此处直接编辑