章节导读
"泛型是Java类型系统中最精妙的设计之一——它让代码在编译期就能发现类型错误,而不是等到运行时抛出ClassCastException才追悔莫及。" —— 大翔,飞翔科技CTO
本章概述
泛型(Generics)是JDK 5引入的一项里程碑式语言特性,也是Java SE 8程序员必须精通的核心技能。本章将从飞翔科技真实业务场景出发,系统讲解泛型的基础概念、底层原理与应用实战。
在你学习Spring框架、编写Repository/Service层代码、使用Stream API时,泛型无处不在。没有扎实的泛型功底,你将无法理解List<String>和List<Integer>为什么在运行时是同一个类,也无法写出类型安全的通用工具类。
为什么这一章至关重要
本章知识地图
| 主题 | 核心内容 | 难度 | 建议学时 |
|---|---|---|---|
| 泛型基础 | 泛型类/接口/方法、类型参数命名约定、原始类型、编译期类型检查 | ★★☆ | 4h |
| 类型擦除 | 擦除机制、无界/有界擦除、桥接方法、擦除带来的限制 | ★★★ | 4h |
| 通配符与PECS | ?、? extends T、? super T、PECS原则、通配符捕获 | ★★★ | 4h |
飞翔科技场景导入
小崔正在开发飞翔科技的"学生管理系统2.0"。架构师白歌审查代码时发现,小崔写了一个通用的Repository接口用于数据库操作,但为了支持不同实体类型(Student、Course、Teacher),他居然写了三个几乎一模一样的接口:
// 小崔的原始写法 —— 代码重复,维护噩梦
public interface StudentRepository {
Student findById(Long id);
void save(Student entity);
List<Student> findAll();
}
public interface CourseRepository {
Course findById(Long id);
void save(Course entity);
List<Course> findAll();
}
public interface TeacherRepository {
Teacher findById(Long id);
void save(Teacher entity);
List<Teacher> findAll();
}
白歌看后只说了一句:"泛型。" 然后拿起键盘,三行代码解决了问题:
// 白歌的泛型写法 —— 一个接口,万用
public interface Repository<T> {
T findById(Long id);
void save(T entity);
List<T> findAll();
}
小崔恍然大悟,但紧接着产生了更多疑问:
T到底是什么?为什么运行时获取不到它的类型信息?List<String>和List<Integer>是同一个类吗?- 为什么不能
new T()? ? extends T和? super T有什么区别?什么时候用哪个?
本章将逐一解答这些问题。
前置知识要求
在开始本章之前,请确保你已经熟练掌握:
- 面向对象基础(第06章):类、对象、继承、多态
- 抽象类与接口(第09章):接口的定义与实现
- 常用类(第11章):String、包装类、Object类
- 集合框架基础概念(List、Set、Map 的 API 了解即可)
学习建议
- 先理解"为什么需要泛型":想象没有泛型时要用Object盛放所有类型,然后强制转型的痛苦——这会让你珍惜泛型的价值。
- 类型擦除是核心:理解了擦除,就理解了泛型的一切限制和行为。强烈建议使用
javap -c -v反编译查看字节码进行验证。 - PECS原则背下来:Producer Extends, Consumer Super——这是泛型面试的高频考点,也是实际编码中最容易出错的地方。
- 边学边练:每读完一节,立即在IDE中编写代码验证。泛型的概念光看是学不会的,必须动手。
本章约定
- 所有示例代码基于 JDK 8 (Java SE 8)
- 默认使用 IntelliJ IDEA 作为IDE
- 场景统一使用 飞翔科技 的业务背景
- 反编译验证使用
javap -c -v命令