文章目录
- 基本概念
- 参数化类型
- 类型安全和编译时检查
- 为什么需要泛型?
- 解决类型安全问题
- 避免重复代码
- 提高可读性和维护性
泛型(Generics)是编程语言中一种支持参数化类型的特性,允许在定义类、接口、方法时使用类型参数(Type Parameters),而在使用时指定具体的类型。泛型的核心目标是提高代码的 类型安全性、可重用性 和 可读性。
基本概念
参数化类型
- 定义时不确定类型:在编写类、接口或方法时使用类型占位符(如
<T>
),实际使用时再传入具体类型(如 String、Integer)。 - 示例:
public class Box<T> {private T content;public void setContent(T content) { this.content = content; }public T getContent() { return content; }
}
// 使用
Box<String> stringBox = new Box<>();
stringBox.setContent("Hello"); // 只能存放 String
类型安全和编译时检查
编译器可以检查参数类型是否正确,并在编译时而不是运行时捕获类型错误。
为什么需要泛型?
解决类型安全问题
在泛型出现之前,Java 集合类(如 ArrayList、HashMap)默认使用 Object 类型存储元素。这导致两个问题:
- 强制类型转换:从集合中取出元素时需要显式转换类型。
- 运行时类型错误风险:如果类型不一致,会抛出
ClassCastException
。
示例:没有泛型的代码
List list = new ArrayList();
list.add("Hello");
list.add(10); // 编译通过(这里的 10 会被自动装箱为 Integer,但类型不一致会埋下隐患)// 取出元素时可能出错
String str = (String) list.get(1); // 运行时抛出 ClassCastException
通过泛型改进后:
List<String> list = new ArrayList<>();
list.add("Hello");
list.add(10); // 编译时就会报错!直接阻止非法操作
String str = list.get(0); // 无需强制类型转换
避免重复代码
在没有泛型时,如果要支持不同类型,需要为每种类型编写相似的代码(如分别实现 IntegerBox
、StringBox
)。
泛型的代码复用:
// 一个泛型类支持所有类型
Box<Integer> intBox = new Box<>();
Box<String> strBox = new Box<>();
提高可读性和维护性
泛型让代码的意图更明确,例如 Map<String, Integer>
清楚地表示“键是String
,值是Integer
”。
- 清晰的类型约束:直接声明数据类型,避免混乱的类型转换。
- 自解释性:代码能直接表达其设计的通用性。