全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-10 8 分钟 ✍️ juanwangdev

泛型与数组

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") 抑制警告

📝 发现内容有误?点击此处直接编辑

← 上一篇 泛型与反射
下一篇 → 泛型与继承
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库