网站首页 > java教程 正文
你是否在Java泛型中见过这些符号:T、?、K/V、extends、super?它们看似简单,却是泛型的核心!泛型不仅是类型安全的守护者,更是代码复用和灵活性的利器。本文将用代码实战带你彻底搞懂它们!
一、基础符号:TvsK/V
1.T:类型占位符
- 作用:定义类/方法时表示具体类型的占位符。
- 场景:泛型类、泛型方法。
// 定义泛型类
public class Box<T> {
private T data;
public void setData(T data) { this.data = data; }
public T getData() { return data; }
}
// 使用
Box<String> stringBox = new Box<>();
stringBox.setData("Hello");
String value = stringBox.getData(); // 直接获取String,无需强转
2.K/V:键值对专用
- 作用:K表示键(Key),V表示值(Value),是T的特殊化。
- 场景:Map、键值对场景。
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
// getters...
}
// 使用
Pair<String, Integer> user = new Pair<>("age", 30);
String key = user.getKey(); // String类型
Integer value = user.getValue(); // Integer类型
二、通配符?:灵活但受限
1. 基础通配符
- 作用:表示未知类型,增强灵活性。
- 限制:只能读(返回Object),不能写(除null外)。
public void printList(List<?> list) {
for (Object elem : list) {
System.out.println(elem); // 可读取
}
// list.add("error"); // 编译错误!不能写入
}
三、边界限定:extends vs super
1.? extends T:生产者(Producer)
- 作用:接受T或其子类,安全读取数据。
- 口诀:Producer Extends(生产者提供数据)。
// 计算任意Number子类列表的总和
public double sum(List<? extends Number> list) {
double total = 0;
for (Number num : list) {
total += num.doubleValue(); // 安全读取
}
return total;
}
// 使用
List<Integer> ints = List.of(1, 2, 3);
sum(ints); // 合法!Integer是Number的子类
2.? super T:消费者(Consumer)
- 作用:接受T或其父类,安全写入数据。
- 口诀:Consumer Super(消费者消费数据)。
// 将数字写入任意Integer父类的列表
public void addNumbers(List<? super Integer> list) {
for (int i = 1; i <= 3; i++) {
list.add(i); // 安全写入
}
}
// 使用
List<Number> numbers = new ArrayList<>();
addNumbers(numbers); // 合法!Number是Integer的父类
四、对比总结:核心区别表
符号 | 使用场景 | 数据方向 | 示例 |
T | 定义泛型类/方法 | 读写 | Box<T> |
K/V | 键值对 | 读写 | Pair<K,V> |
? | 未知类型 | 只读 | List<?> |
? extends T | 读取数据(生产者) | 只读 | List<? extends Number> |
? super T | 写入数据(消费者) | 只写 | List<? super Integer> |
五、实战应用:PECS原则
PECS(Producer-Extends, Consumer-Super) 是泛型使用的黄金法则:
// Java集合框架的copy方法
public static <T> void copy(
List<? super T> dest, // 消费者:写入目标
List<? extends T> src // 生产者:读取源
) {
for (int i = 0; i < src.size(); i++) {
dest.add(src.get(i)); // 从src读,向dest写
}
}
// 使用
List<Integer> src = List.of(1, 2, 3);
List<Number> dest = new ArrayList<>();
Collections.copy(dest, src); // 安全复制!
六、为什么泛型如此重要?
- 类型安全:避免ClassCastException。
- 代码复用:一套逻辑处理多种类型。
- 代码清晰:减少强制类型转换。
结语
掌握泛型符号的区别,是写出高质量Java代码的关键!记住:
- T/K/V用于定义类型;
- ?提供灵活性;
- extends和super通过PECS原则控制数据流向。
下次遇到泛型时,你会自信地说:So easy!
- 上一篇: 泛型常用特点_泛型的种类
- 下一篇:已经是最后一篇了
猜你喜欢
- 2025-09-04 泛型常用特点_泛型的种类
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)