1. 什么是泛型
泛型(Generic) :JDK 1.5 引入的特性,本质是 参数化类型(Parameterized Type),即把数据类型作为参数传递给类、接口或方法。
解决的问题 :在编译期约束和检查类型,避免运行时的
ClassCastException
,同时提高代码复用性。👉 没有泛型前:
javaList list = new ArrayList(); list.add("Hello"); list.add(123); // 不小心加了一个整数 String s = (String) list.get(1); // 运行时才抛出 ClassCastException
👉 使用泛型后:
javaList<String> list = new ArrayList<>(); list.add("Hello"); // list.add(123); // 编译期直接报错 String s = list.get(0); // 无需强转
2. 泛型的核心好处
类型安全:在编译期检查类型。
避免强制类型转换:减少冗余代码。
代码复用:同一份代码可作用于不同的数据类型。
3. 泛型的使用场景
泛型主要可以用在 类、接口、方法 上。
3.1 泛型类
java// 定义一个泛型类 public class Box<T> { private T value; public void set(T value) { this.value = value; } public T get() { return value; } } // 使用 Box<String> box1 = new Box<>(); box1.set("Hello"); String str = box1.get(); Box<Integer> box2 = new Box<>(); box2.set(100); Integer num = box2.get();
- T 是一个占位符,实际使用时由具体类型替换。
3.2 泛型接口
java// 泛型接口 public interface Generator<T> { T next(); } // 实现方式一:指定类型 class StringGenerator implements Generator<String> { @Override public String next() { return "Hello"; } } // 实现方式二:继续保持泛型 class GenericGenerator<T> implements Generator<T> { private T value; public GenericGenerator(T value) { this.value = value; } @Override public T next() { return value; } }
3.3 泛型方法
javapublic class GenericMethodDemo { // 泛型方法(返回值前加 <T> 表示这是一个泛型方法) public static <T> void printArray(T[] array) { for (T item : array) { System.out.println(item); } } } // 使用 String[] strs = {"A", "B", "C"}; GenericMethodDemo.printArray(strs); Integer[] nums = {1, 2, 3}; GenericMethodDemo.printArray(nums);
4. 泛型的通配符(Wildcard)
通配符
?
表示 未知类型,主要用于增强泛型的灵活性。4.1 无界通配符
?
javapublic void printList(List<?> list) { for (Object o : list) { System.out.println(o); } }
List<?>
可以接收任何泛型类型的List
。
4.2 有界通配符
<? extends T>
:上界,类型必须是T
或T
的子类。
<? super T>
:下界,类型必须是T
或T
的父类。上界通配符(读取安全)
javapublic void readList(List<? extends Number> list) { Number num = list.get(0); // 安全 // list.add(10); // 编译错误:不能保证类型 }
下界通配符(写入安全)
javapublic void writeList(List<? super Integer> list) { list.add(10); // 可以写入 Integer 或其子类 Object obj = list.get(0); // 读取时只能作为 Object }
💡 口诀:
- 生产者用 extends,消费者用 super(PECS 原则)。
5. 泛型的类型擦除
Java 的泛型只在 编译期有效 ,运行时会进行 类型擦除,即替换为原始类型(Raw Type)。
javaList<String> list1 = new ArrayList<>(); List<Integer> list2 = new ArrayList<>(); System.out.println(list1.getClass() == list2.getClass()); // true
运行时
list1
和list2
都是ArrayList
。泛型信息会在编译后擦除,因此不会生成多个类。
6. 泛型与数组的区别
数组是协变的 :
Integer[]
可以赋值给Number[]
。泛型是不可变的 :
List<Integer>
不能赋值给List<Number>
。
javaNumber[] nums = new Integer[10]; // 合法 // List<Number> list = new ArrayList<Integer>(); // 编译错误
7. 泛型的限制
不能使用基本类型 :
List<int>
错误,只能用包装类List<Integer>
。不能创建泛型数组 :
new T[10]
错误。静态变量不能使用类型参数。
类型擦除后不能区分方法重载。
8. 常见应用
集合框架 :
List<E>
,Map<K,V>
。工具类 :
Collections.sort(List<T> list)
。自定义泛型工具:
javapublic class Pair<K, V> { private K key; private V value; public Pair(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } }
9. 小结
泛型本质:编译期的类型安全检查 + 类型擦除。
核心用法:泛型类、泛型接口、泛型方法。
灵活性工具:通配符(?、extends、super)。
限制:不能直接使用基本类型,数组和泛型有区别,运行时会类型擦除。
原则:生产者 extends,消费者 super (PECS)。
java--泛型
你我约定有三2025-09-08 10:23
相关推荐
杨杨杨大侠4 小时前
第3章:实现基础事件总线杨杨杨大侠4 小时前
第4章:添加注解支持小苏兮4 小时前
【C++】类与对象(下)咖啡Beans4 小时前
异步处理是企业开发的‘生存之道’!Java8和Spring的异步实现,你必须搞清楚!self_myth5 小时前
[特殊字符] 深入理解操作系统核心特性:从并发到分布式,从单核到多核的全面解析间彧5 小时前
Java中T类型详解与实际使用凯子坚持 c5 小时前
C++ 连接 Redis:redis-plus-plus 安装与使用入门指南正在走向自律5 小时前
Ubuntu系统下Python连接国产KingbaseES数据库实现增删改查草莓熊Lotso5 小时前
PyCharm 从入门到高效:安装教程 + 快捷键速查表