一、泛型核心价值
类型安全与代码复用的平衡艺术,主要解决以下问题:
避免强制类型转换错误(ClassCastException)
增强代码可读性和可维护性
实现通用算法和数据结构
二、基础用法规范
2.1 泛型类定义
// 标准容器类示例
public class Box
private T content;
public void put(T item) {
this.content = item;
}
public T get() {
return content;
}
}
// 使用示例
Box
stringBox.put("Hello");
String value = stringBox.get(); // 无需强制转型
2.2 泛型方法实现
// 通用数组交换方法
public class ArrayUtils {
public static
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
// 使用示例
String[] names = {
"Alice", "Bob"};
ArrayUtils.swap(names, 0, 1);
三、类型参数约束
3.1 边界限定(Bounded Type)
// 数值计算接口
public interface Calculator
double calculate(T a, T b);
}
// 具体实现
public class AddCalculator implements Calculator
@Override
public double calculate(Double a, Double b) {
return a + b;
}
}
3.2 多重边界
// 同时实现Serializable和Comparable
public class MultiBound
public void sort(List
Collections.sort(list);
}
}
四、通配符高级应用
4.1 三种通配符对比
类型
语法
适用场景
写入限制
无界通配符
>
只读操作
不能写入
上界通配符
extends T>
读取T及其子类对象
只能写入null
下界通配符
super T>
写入T及其父类对象
可以写入T对象
4.2 生产者-消费者模式
// 生产者使用extends
public static void processProducers(List extends Number> list) {
for (Number n : list) {
System.out.println(n.doubleValue());
}
}
// 消费者使用super
public static void addIntegers(List super Integer> list) {
for (int i = 0; i < 5; i++) {
list.add(i);
}
}
五、类型擦除应对策略
5.1 运行时类型信息保留
// 通过Class对象传递类型信息
public class TypeSafeMap {
private Map
public
map.put(type, instance);
}
public
return type.cast(map.get(type));
}
}
// 使用示例
TypeSafeMap safeMap = new TypeSafeMap();
safeMap.put(String.class, "Secret");
String value = safeMap.get(String.class);
5.2 泛型数组创建
// 正确创建泛型数组方法
public class ArrayFactory {
@SuppressWarnings("unchecked")
public static
return (T[]) Array.newInstance(type, size);
}
}
// 使用示例
String[] strings = ArrayFactory.createArray(String.class, 10);
六、典型应用场景
6.1 通用DAO接口
public interface BaseDao
T findById(ID id);
List
void save(T entity);
void delete(ID id);
}
// 具体实现
public class UserDao implements BaseDao
// 实现接口方法...
}
6.2 事件总线系统
public class EventBus {
private Map
public
handlers.computeIfAbsent(eventType, k -> new ArrayList<>()).add(handler);
}
@SuppressWarnings("unchecked")
public
List
if (consumers != null) {
consumers.forEach(consumer -> ((Consumer
}
}
}
七、常见错误及修正
7.1 原生类型使用
// 错误示例
List rawList = new ArrayList();
rawList.add("String");
rawList.add(10); // 编译通过但运行危险
// 修正方案
List
safeList.add("Hello");
// safeList.add(10); // 编译错误
7.2 泛型数组初始化
// 错误示例
T[] array = new T[10]; // 编译错误
// 正确方法
T[] array = (T[]) new Object[10]; // 需配合类型转换
八、最佳实践总结
命名规范:使用有意义的类型参数名称(如
边界控制:尽可能使用最严格的类型约束
通配符策略:• PECS原则(Producer-Extends, Consumer-Super)• 返回值不使用通配符
类型安全:• 优先使用泛型方法而非原生类型• 利用@SuppressWarnings时添加明确注释
文档规范:在复杂泛型类中增加类型参数说明
九、扩展知识接口
9.1 获取泛型参数类型
public abstract class TypeToken
private final Type type;
protected TypeToken() {
Type superClass = getClass().getGenericSuperclass();
this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
public Type getType() {
return type;
}
}
// 使用示例
Type stringType = new TypeToken
}.getType();
9.2 泛型与反射结合
public class GenericReflection {
public static void printTypeParameters(Class> clazz) {
TypeVariable>[] typeParams = clazz.getTypeParameters();
for (TypeVariable> param : typeParams) {
System.out.println("Type parameter: " + param.getName());
for (Type bound : param.getBounds()) {
System.out.println(" Bound: " + bound.getTypeName());
}
}
}
}
// 分析List接口
GenericReflection.printTypeParameters(List.class);
通过合理应用泛型技术,可以显著提升代码的健壮性和可维护性。建议在复杂泛型场景中使用IDE的代码检查功能,并配合单元测试验证类型安全性。随着Java版本的演进(如引入var),泛型的使用方式也在不断优化,需要持续关注语言新特性。