当前位置: 首页 > news >正文

【从零开始java学习|第二十三篇】泛型体系与通配符

泛型是 Java 集合框架的核心特性之一,它通过参数化类型实现代码复用与类型安全。以下从泛型类、泛型方法、泛型接口、泛型通配符四个维度展开,并结合集合的继承关系说明其应用。

一、泛型类:集合的 “容器模板”

定义与语法

泛型类是在类定义时引入类型参数(如 <T>),使类的成员(变量、方法)可操作任意类型。集合框架中,ArrayList<E>HashMap<K,V> 等均为泛型类。

// 自定义泛型类:MyList<T>,模拟ArrayList的简化版
class MyList<T> {private Object[] elements;private int size;public MyList() {elements = new Object[10];}// 泛型方法:添加元素(T类型)public void add(T item) {elements[size++] = item;}// 泛型方法:获取元素(返回T类型)public T get(int index) {return (T) elements[index];}
}

集合中的应用

  • ArrayList<E>:通过泛型类实现 “动态数组”,元素类型由<E>指定,避免装箱拆箱开销。
  • HashMap<K,V>:键值对的泛型类,<K>为键类型,<V>为值类型,保证键值对的类型安全。

二、泛型方法:集合工具的 “通用逻辑”

定义与语法

泛型方法是在方法返回值前声明类型参数(如 <T>),使其独立于类的泛型参数。集合工具类Collections中的sortbinarySearch等均为泛型方法。

// 自定义泛型方法:打印任意类型数组
public class CollectionUtils {public static <T> void printArray(T[] array) {for (T item : array) {System.out.print(item + " ");}System.out.println();}
}

泛型不具备继承性

泛型类型之间不存在继承关系,即使两个类存在继承关系,使用它们作为泛型参数的泛型类型之间也不会自动具有继承关系。例如,假设有类Animal和它的子类DogArrayList<Dog> 不是 ArrayList<Animal> 的子类。

用代码示例可以更直观地说明:

import java.util.ArrayList;class Animal {}
class Dog extends Animal {}public class GenericInheritanceTest {public static void main(String[] args) {// 编译错误,因为ArrayList<Dog>不是ArrayList<Animal>的子类// ArrayList<Animal> animalList = new ArrayList<Dog>(); }
}

之所以会出现编译错误,是因为泛型类型的设计目的是提供类型安全。如果允许ArrayList<Dog> 是 ArrayList<Animal> 的子类,那么当从ArrayList<Animal>中获取元素时,编译器无法保证获取到的一定是Animal,可能会导致运行时的类型转换异常。比如:

import java.util.ArrayList;class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}public class GenericInheritanceError {public static void main(String[] args) {ArrayList<Dog> dogList = new ArrayList<>();dogList.add(new Dog());// 假设允许这样的赋值ArrayList<Animal> animalList = dogList; animalList.add(new Cat()); // 这里编译时不会报错Dog dog = dogList.get(1); // 运行时会抛出ClassCastException,因为索引1处是Cat对象}
}

数据具备继承性

虽然泛型类型本身不具备继承性,但存储在泛型集合中的数据是具备继承性的。当定义一个泛型集合,比如ArrayList<Animal> 时,由于DogCat 等类继承自Animal,所以可以将DogCat 等Animal子类的对象添加到ArrayList<Animal> 中。

示例代码如下:

import java.util.ArrayList;class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}public class DataInheritanceTest {public static void main(String[] args) {ArrayList<Animal> animalList = new ArrayList<>();animalList.add(new Dog()); // 可以添加Animal的子类对象animalList.add(new Cat());for (Animal animal : animalList) {// 可以按照Animal类型进行处理,也可以根据实际类型进行类型转换后处理System.out.println(animal.getClass().getSimpleName()); }}
}

这是因为 Java 的继承机制允许子类对象替代父类对象出现在需要父类对象的地方,也就是常说的里氏替换原则。在泛型集合中,只要集合声明的泛型类型是数据类型的父类,那么就可以将数据类型(子类)的对象添加进去,并且在遍历处理这些对象时,可以按照父类的方式统一处理,也可以根据实际的子类类型进行针对性处理。

集合中的应用

  • Collections.sort(List<T>):通过泛型方法实现对任意List的排序,类型由<T>自动推断。
  • Stream<T> map(Function<T, R>):Stream API 的泛型方法,支持链式操作中的类型转换。

三、泛型接口:集合的 “行为契约”

定义与语法

泛型接口是在接口定义时引入类型参数(如 <E>),实现类需指定具体类型或继续使用泛型。集合框架中,List<E>Set<E>Map<K,V> 均为泛型接口。

// 自定义泛型接口:表示“可迭代”的集合
interface Iterable<T> {Iterator<T> iterator();
}// 实现类:ArrayList实现Iterable<E>
class ArrayList<E> implements Iterable<E> {@Overridepublic Iterator<E> iterator() {return new ArrayListIterator();}private class ArrayListIterator implements Iterator<E> {// 迭代逻辑...}
}

集合中的应用

  • List<E>:定义 “有序集合” 的契约,子类(如ArrayListLinkedList)需实现其方法。
  • Comparable<T>:泛型接口,用于对象排序(如Integer实现Comparable<Integer>)。

四、泛型通配符:处理集合的 “继承关系”

泛型本身不支持协变(子类型自动转换),需通过通配符(?? extends T? super T)解决集合的继承兼容问题。

1. 无界通配符 ?

表示 “任意类型”,用于集合仅需操作Object方法(如toString()equals())的场景。

// 打印任意类型的集合
public static void printCollection(Collection<?> coll) {for (Object item : coll) {System.out.println(item);}
}

集合中的应用

  • 通用工具方法(如打印任意ListSet)。

2. 上限通配符 ? extends T

表示 “TT的子类”,遵循PECS 原则(Producer Extends)—— 仅用于 “读取” 数据(生产者)。

// 计算数值集合的总和(T必须是Number的子类)
public static double sum(Collection<? extends Number> nums) {double total = 0;for (Number num : nums) {total += num.doubleValue();}return total;
}

集合中的应用

  • List<? extends Number> 可接收List<Integer>List<Double>等,实现数值类型的统一处理。

3. 下限通配符 ? super T

表示 “TT的父类”,遵循PECS 原则(Consumer Super)—— 仅用于 “写入” 数据(消费者)。

// 向集合中添加整数(集合类型必须是Integer或其父类)
public static void addIntegers(List<? super Integer> list) {list.add(10);list.add(20);
}

集合中的应用

  • List<? super Integer> 可接收List<Integer>List<Number>List<Object>,实现数据的向上兼容存储。

4. 泛型继承关系的处理

泛型不支持直接协变(如List<Integer>不是List<Number>的子类),但通过通配符可间接建立关系:

// 错误:泛型不支持直接协变
// List<Number> nums = new ArrayList<Integer>(); // 正确:通过上限通配符建立关系
List<? extends Integer> intList = new ArrayList<Integer>();
List<? extends Number> numList = intList; // 合法,因为Integer是Number的子类

五、总结:泛型在集合中的核心价值

  1. 类型安全:编译期检查集合元素类型,避免ClassCastException
  2. 代码复用:泛型类 / 方法 / 接口实现 “一次编写,多类型适用”(如ArrayList可存储任意类型)。
  3. 灵活兼容:通配符(? extends T? super T)解决泛型与继承的兼容问题,适配复杂场景。

如果我的内容对你有帮助,请点赞,评论,收藏。接下来我将继续更新相关内容!

http://www.dtcms.com/a/482800.html

相关文章:

  • 有哪些做室内设计好用的网站wordpress+chrome+扩展
  • CRMEB多商户系统(PHP)v3.3正式发布,同城配送上线[特殊字符]
  • Flink 作业通用优化方案
  • deepseek改写的dlx算法求解数独rust程序
  • Leetcode 3715. Sum of Perfect Square Ancestors
  • 四川省建设厅门户网站男女做床网站
  • 语义循环的幽灵——循环解释悖论对NLP深层语义分析的影响与启示
  • 项目沟通与冲突管理
  • 网站引导页案例免费的制作手机网站平台
  • linux学习笔记(32)网络编程——UDP
  • 2025全新三防平板科普:5G-A+卫星通信+国产化
  • 电商网站建设懂你所需wordpress一句话木马
  • 「机器学习笔记14」集成学习全面解析:从Bagging到Boosting的Python实战指南
  • 小迪安全v2023学习笔记(一百三十一讲)—— Web权限提升篇划分获取资产服务后台系统数据库管理相互转移
  • Java高并发知识
  • 2025年渗透测试面试题总结-204(题目+回答)
  • 复制 201/220 Dump 需要用什么?
  • idc网站备案中国与菲律宾最新事件
  • 深圳网站建设公司首选宜昌营销型网站
  • 美丽乡村 村级网站建设网站 繁体 js
  • Git 大文件上传失败深度解析与终极解决方案_含 macOS_Windows 全流程20251014
  • Starting again myself 03
  • 网站改版申请网站备案密码使用
  • 视频模型的主流结构
  • Java SpringIoCDI --- @Bean,DI
  • 深度学习与舌诊的结合:人工智能助力中医诊断新时代
  • 分治:最大子段和
  • 从江网站建设松江企业网站建设
  • 贪心算法精选30道编程题 (附有图解和源码)
  • 五莲县财源建设网站为什么网站建设图片显示不出来