泛型(Generics)是Java 5引入的核心特性,用于在编译期提供类型安全检查并消除强制类型转换,提高代码复用性和可读性。
一、核心概念
类型参数化
- 将类型作为参数传递给类、接口或方法
- 语法:
<T>
(T为类型占位符)
类型擦除
- 泛型信息在编译后被擦除(替换为Object或边界类型)
- 运行时无法获取泛型具体类型(如
List<String>
运行时变为List
) - 擦除规则:
- 无边界:
<T>
→Object
- 有上界:
<T extends Number>
→Number
- 有下界:
<T super Integer>
→Object
- 无边界:
泛型的好处
- 类型安全:通过泛型,编译器可以在编译时检查类型,避免运行时出现ClassCastException。
- 消除强制类型转换:使用泛型后,代码更加清晰,不需要进行显式的类型转换。
- 提高代码的重用性:可以编写通用的算法和数据结构,适用于多种数据类型。
二.泛型类
泛型类是指在定义类时使用类型参数。类型参数可以在类的内部作为成员变量的类型、方法的参数类型和返回值类型。
允许创建类型安全的容器,核心优势:
- 一次定义可支持多种类型
- 编译时类型检查避免ClassCastException
- 消除代码中的强制类型转换
// 定义一个泛型类Box,T是类型参数
class Box<T> {
private T value;
// 构造方法,用于初始化value
public Box(T value) {
this.value = value;
}
// 获取value的方法
public T getValue() {
return value;
}
// 设置value的方法
public void setValue(T value) {
this.value = value;
}
}
// 测试泛型类
public class GenericClassExample {
public static void main(String[] args) {
// 创建一个存储Integer类型的Box对象
Box<Integer> integerBox = new Box<>(10);
// 获取存储的值
Integer intValue = integerBox.getValue();
System.out.println("Integer value: " + intValue);
// 创建一个存储String类型的Box对象
Box<String> stringBox = new Box<>("Hello, World!");
// 获取存储的值
String stringValue = stringBox.getValue();
System.out.println("String value: " + stringValue);
}
}
代码解释
Box<T>
是一个泛型类,其中T
是类型参数,可以在类的内部使用。value
是一个泛型类型的成员变量,其类型由创建对象时指定。getValue()
方法返回T
类型的值,setValue(T value)
方法接受一个T
类型的参数。- 在
main
方法中,我们创建了两个Box
对象,一个存储Integer
类型的值,另一个存储String
类型的值。
三.泛型方法
泛型方法是指在定义方法时使用类型参数。泛型方法可以在普通类中定义,也可以在泛型类中定义。
泛型方法独立于类提供类型安全操作:
- 方法声明前定义类型参数:
<T> returnType method()
- 支持类型推断(编译器自动确定类型)
- 可定义比类更灵活的类型约束
- 常用于工具类和静态方法
public class GenericMethodExample {
// 定义一个泛型方法,用于打印数组元素
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
public static void main(String[] args) {
// 创建一个Integer数组
Integer[] intArray = {1, 2, 3, 4, 5};
// 调用泛型方法打印Integer数组
printArray(intArray);
// 创建一个String数组
String[] stringArray = {"Hello", "World", "Java"};
// 调用泛型方法打印String数组
printArray(stringArray);
}
}
代码解释
<T>
是泛型方法的类型参数,位于方法返回类型之前。printArray(T[] array)
方法接受一个泛型数组作为参数,并打印数组中的元素。- 在
main
方法中,我们分别创建了一个Integer
数组和一个String
数组,并调用printArray()
方法打印数组元素。
四.泛型接口
泛型接口是指在定义接口时使用类型参数。实现泛型接口的类可以指定具体的类型,也可以继续使用泛型。
泛型接口的两种实现方式:
- 实现类给出具体的类型
- 实现类延续泛型,创建实现类对象时在确定类型
// 定义一个泛型接口Generator
interface Generator<T> {
T generate();
}
// 实现泛型接口,指定具体类型为Integer
class IntegerGenerator implements Generator<Integer> {
@Override
public Integer generate() {
return (int) (Math.random() * 100);
}
}
// 实现泛型接口,继续使用泛型
class GenericGenerator<T> implements Generator<T> {
private T value;
public GenericGenerator(T value) {
this.value = value;
}
@Override
public T generate() {
return value;
}
}
// 测试泛型接口
public class GenericInterfaceExample {
public static void main(String[] args) {
// 创建IntegerGenerator对象
IntegerGenerator integerGenerator = new IntegerGenerator();
// 调用generate方法生成随机整数
Integer randomInt = integerGenerator.generate();
System.out.println("Random integer: " + randomInt);
// 创建GenericGenerator对象,存储String类型的值
GenericGenerator<String> stringGenerator = new GenericGenerator<>("Hello, Generic!");
// 调用generate方法获取存储的值
String stringValue = stringGenerator.generate();
System.out.println("String value: " + stringValue);
}
}
代码解释
Generator<T>
是一个泛型接口,其中T
是类型参数,generate()
方法返回T
类型的值。IntegerGenerator
类实现了Generator<Integer>
接口,指定具体类型为Integer
,并实现了generate()
方法。GenericGenerator<T>
类实现了Generator<T>
接口,继续使用泛型,generate()
方法返回存储的值。