网站首页 > 技术文章 正文
你是否在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-10-19 MYSQL有哪些数据类型_mysql哪些数据类型没有长度
- 2025-10-19 个人C++笔记(2) 函数延伸(下)函数重载
- 2025-10-19 Java 7种类类型,新手必备_java的类型
- 2025-10-19 Java泛型最全详解(图文全面总结)_java 泛型 ?
- 2025-10-19 Java基础——基本类型_java的基本类型的区别
- 2025-10-19 02010501 类的基本概念_0901类别
- 2024-08-11 数据类型有哪些?(可变数据类型有哪些)
- 2024-08-11 zig编程语言快速入门——2.15 基础知识-Integer
- 2024-08-11 Java基础 | 基本数据类型(java基本数据类型主要包括)
- 2024-08-11 java Integer值比较(java integer 比较)
- 最近发表
-
- 用Cursor开启JAVA+AI生涯_javascirpt怎么开启
- 大数据调度服务监控平台_大数据调度是什么意思
- SpringBoot、MyBatis、Vue搭建一个Java企业应用开源框架源码分享
- 大数据技术之Flume_大数据volume的含义
- Jenkins运维之路(Slave容器节点)_jenkins slave工作原理
- 程序员自救指南:IDEA 卡成狗?我的 9G 堆内存调参表让你起飞 附避坑
- JMeter:一个简单的测试计划怎么做?
- Windows 命令行终端 PowerShell 美化计划
- JDK25即将发布!新特性概览_jdk52.0
- JDK 25 新特性极简总结(2025 年 9 月 16 日发布,LTS 长期支持)
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- c语言min函数头文件 (77)
- asynccallback (87)
- localstorage.removeitem (77)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 无效的列索引 (74)