Java泛型的定义基础
Java泛型(Generics)是Java SE 5.0引入的一项重要特性,它允许在定义类、接口或方法时使用类型参数,从而在编译阶段进行类型检查,避免运行时的类型转换异常,泛型的核心思想是“参数化类型”,即通过类型变量来表示未知的数据类型,提高代码的复用性和安全性。

泛型类的定义
泛型类的定义需要在类名后面紧跟一对尖括号<>,并在尖括号内声明类型参数,类型参数通常使用单个大写字母表示,如T、E、K、V等,这些字母仅作为占位符,实际类型在使用时由调用者指定,定义一个泛型类Box,用于存储任意类型的对象:
public class Box<T> {
private T content;
public void setContent(T content) {
this.content = content;
}
public T getContent() {
return content;
}
}
使用时,通过指定具体类型来创建实例,如Box<String>表示存储字符串的盒子,Box<Integer>表示存储整数的盒子,编译器会确保类型的一致性,例如不能将Integer类型的对象存入Box<String>中。
泛型接口的定义
泛型接口的定义与泛型类类似,接口名称后需添加类型参数,定义一个泛型接口Repository,用于规范数据访问操作:
public interface Repository<T> {
void save(T entity);
T findById(Long id);
List<T> findAll();
}
实现类需要指定具体的类型参数,如UserRepository实现Repository<User>,专门处理用户数据的存取,这种方式既保证了接口的通用性,又避免了类型转换的麻烦。

泛型方法的定义
泛型方法可以在普通类或泛型类中定义,其类型参数位于修饰符和返回类型之间,定义一个泛型方法printArray,用于打印任意类型的数组:
public class ArrayUtils {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
}
调用时,编译器会根据传入的参数自动推断类型,如printArray(new Integer[]{1, 2, 3})或printArray(new String[]{"A", "B", "C"}),泛型方法的优势在于灵活性,无需依赖类的泛型声明即可独立使用。
泛型通配符与边界
泛型通配符用于表示未知类型,分为无界通配符、上界通配符? extends T和下界通配符? super T。
- 无界通配符:
List<?>表示可以存储任意类型的列表,但无法修改列表内容(除null外)。 - 上界通配符:
List<? extends Number>表示可以存储Number及其子类(如Integer、Double)的列表,适用于读取操作。 - 下界通配符:
List<? super Integer>表示可以存储Integer及其父类(如Number、Object)的列表,适用于写入操作。
泛型的类型擦除
Java泛型在编译后会发生类型擦除,即泛型类型在运行时被替换为原始类型(Object或边界类型)。Box<String>和Box<Integer>在运行时都是Box类型,这意味着泛型不能用于运行时类型检查,如instanceof操作,也无法创建泛型数组(如new T[])。

Java泛型通过类型参数、泛型类/接口/方法、通配符等机制,实现了代码的类型安全和复用,合理使用泛型可以减少强制类型转换,避免ClassCastException,同时提升代码的可读性和可维护性,开发者需注意类型擦除带来的限制,在设计和使用泛型时综合考虑编译时检查与运行时行为的差异。

















