Java语法基础中泛型的上限和下限如何定义

兄弟们在线讲解下,Java语法基础中泛型的上限和下限如何定义
最新回答
路遥归梦

2026-10-23 16:16:42

在Java语法基础中,泛型的上限和下限通过通配符?配合extends和super关键字定义,用于限制泛型类型的范围,提高类型安全性并保持灵活性。其核心规则与使用场景如下:

1. 泛型上限:? extends T
  • 定义:使用? extends T表示泛型类型必须是T或其子类(即类型上限为T)。
  • 适用场景:“只读”操作(生产者场景,Producer-Extends)。

    可以从集合中安全读取元素,编译器会将元素视为T类型或其父类,确保类型兼容。

    禁止写入(除null外),因为编译器无法确定集合的具体类型(可能是T的任意子类)。

  • 示例:List<? extends Number> list = new ArrayList<Integer>();Number n = list.get(0); // 合法:读取为Number类型// list.add(new Integer(1)); // 编译错误:无法确定具体类型

    原因:list可能是List<Integer>、List<Double>等,编译器无法保证添加的元素与实际类型匹配。

2. 泛型下限:? super T
  • 定义:使用? super T表示泛型类型必须是T或其父类(即类型下限为T)。
  • 适用场景:“只写”操作(消费者场景,Consumer-Super)。

    可以向集合中安全写入T类型的对象,因为集合的实际类型一定是T或其父类。

    读取限制:只能以Object类型接收元素,因为编译器无法确定集合的具体类型(可能是T的任意父类)。

  • 示例:List<? super Integer> list = new ArrayList<Number>();list.add(new Integer(1)); // 合法:可以添加IntegerObject obj = list.get(0); // 只能以Object类型读取

    原因:list可能是List<Number>、List<Object>等,取出的对象无法保证具体类型。

3. PECS原则(Producer-Extends, Consumer-Super)
  • 核心思想:根据操作方向选择通配符:

    生产者(Producer):若集合主要用于提供数据(读取),使用? extends T。

    消费者(Consumer):若集合主要用于接收数据(写入),使用? super T。

  • 示例场景:

    复制元素时,源集合作为生产者用? extends T,目标集合作为消费者用? super T:public static <T> void copy(List<? super T> dest, List<? extends T> src) { for (T t : src) { dest.add(t); }}

4. 读写混合场景
  • 若集合需要同时读写,应避免使用通配符,直接使用具体泛型类型(如List<T>)。
  • 原因:通配符会限制操作灵活性,例如:List<? extends Number> list;// list.add(new Integer(1)); // 编译错误(无法写入)// Number n = list.get(0); // 合法,但无法写入
5. 关键总结
  • ? extends T:

    读安全:元素可视为T类型。

    写限制:禁止添加非null对象。

  • ? super T:

    写安全:可添加T类型对象。

    读限制:元素只能视为Object类型。

  • PECS原则:根据数据流向选择通配符,确保类型安全与操作灵活性。

通过理解类型安全与操作方向的关系,可以更高效地使用Java泛型上限和下限。