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

泛型与集合

泛型(Generics)是 Java 5 引入的特性,让集合可以指定元素类型。

泛型的作用

作用说明
类型安全编译期检查类型,避免运行时错误
消除转型无需手动类型转换
代码清晰明确集合元素类型

无泛型 vs 有泛型

无泛型(Java 5 之前)

Java
List list = new ArrayList();
list.add("Hello");
list.add(100);           // 编译通过,运行时可能出错

String s = (String) list.get(0);  // 需手动转型
Integer i = (Integer) list.get(1);  // 可能 ClassCastException

有泛型

Java
List<String> list = new ArrayList<>();
list.add("Hello");
list.add(100);           // 编译错误,类型不匹配

String s = list.get(0);  // 无需转型

泛型集合基本用法

Java
// List 泛型
List<String> strings = new ArrayList<>();
List<Integer> integers = new ArrayList<>();

// Set 泛型
Set<String> names = new HashSet<>();

// Map 泛型(键和值都指定类型)
Map<String, Integer> scores = new HashMap<>();
scores.put("张三", 90);
int score = scores.get("张三");  // 无需转型

// 多层嵌套泛型
Map<String, List<Integer>> map = new HashMap<>();

泛型方法

Java
// 泛型方法
public static <T> T getFirst(List<T> list) {
    return list.isEmpty() ? null : list.get(0);
}

// 使用
String first = getFirst(Arrays.asList("A", "B"));
Integer firstNum = getFirst(Arrays.asList(1, 2, 3));

类型擦除

Java 泛型通过类型擦除实现:

Java
List<String> strings = new ArrayList<>();
List<Integer> integers = new ArrayList<>();

// 运行时两者都是 ArrayList,泛型信息被擦除
System.out.println(strings.getClass() == integers.getClass());  // true

类型擦除后果

  • 运行时无法获取泛型具体类型
  • 不能创建泛型数组:new List<String>[10](非法)
  • 不能创建泛型实例:new T()(非法)

泛型通配符

无界通配符

Java
// 可以接收任何类型的 List
public void printList(List<?> list) {
    for (Object item : list) {
        System.out.println(item);
    }
}

限制:List 只能读取(作为 Object),不能添加(除 null)。

上界通配符 <? extends T>

Java
// 可以接收 T 或 T 的子类
public double sum(List<? extends Number> list) {
    double total = 0;
    for (Number num : list) {
        total += num.doubleValue();
    }
    return total;
}

// 使用
sum(Arrays.asList(1, 2, 3));            // List<Integer>
sum(Arrays.asList(1.0, 2.0, 3.0));      // List<Double>

限制:List<? extends Number> 只能读取,不能添加。

下界通配符 <? super T>

Java
// 可以接收 T 或 T 的父类
public void addNumbers(List<? super Integer> list) {
    list.add(1);
    list.add(2);
    list.add(3);  // 可以添加 Integer
}

// 使用
List<Number> numbers = new ArrayList<>();
addNumbers(numbers);  // List<Number>

List<Object> objects = new ArrayList<>();
addNumbers(objects);  // List<Object>

特点:List<? super Integer> 可以添加 Integer,读取只能作为 Object。

PECS 原则

Producer-Extends, Consumer-Super

  • Producer(生产者/读取):用 ? extends T
  • Consumer(消费者/写入):用 ? super T
Java
// 从集合读取 → extends
public void read(List<? extends Number> source) {
    Number n = source.get(0);  // 读取
}

// 向集合写入 → super
public void write(List<? super Integer> target) {
    target.add(1);  // 写入
}

// 复制:src读取(dst),dst写入(src)
public void copy(List<? extends Number> src, List<? super Number> dst) {
    for (Number n : src) {
        dst.add(n);
    }
}

要点总结

  • 泛型保证类型安全,消除手动转型
  • List、Map<K, V> 指定元素类型
  • Java 泛型通过类型擦除实现,运行时无泛型信息
  • PECS:生产者用 extends,消费者用 super

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

← 上一篇 并发集合
下一篇 → 集合工具类 Collections
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

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

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