一、核心原理
1. 类型擦除机制
- 编译期类型检查:泛型信息用于编译时类型验证
- 运行时擦除:所有泛型类型参数被替换为边界类型(无限定时为Object)
- 桥接方法:编译器自动生成保证多态性的适配方法
2. 类型安全保证
- 编译时强制类型检查
- 自动装箱/拆箱优化
- 避免强制类型转换
二、语法要素
1. 类型参数声明
java
// 通用形式
public class ClassName<T, E extends Number & Serializable> { ... }
// 单类型参数简写
public interface List<E> extends Collection<E> { ... }
2. 类型参数命名规范
符号 | 语义 | 典型场景 |
---|---|---|
T | Type | 通用类型 |
E | Element | 集合元素 |
K/V | Key/Value | 映射关系 |
N | Number | 数值类型 |
? | Unbounded Wildcard | 未知类型 |
三、核心应用场景
1. 泛型类定义
java
public class DataContainer<T> {
private T data;
public void setData(T data) { this.data = data; }
public T getData() { return data; }
// 类型参数可用作方法返回值
public T getDefault() { return data; }
}
2. 泛型接口实现
java
// 定义带类型参数的函数式接口
@FunctionalInterface
public interface Mapper<T, R> {
R apply(T input);
}
// 实现类指定具体类型
public class StringToIntegerMapper implements Mapper<String, Integer> {
@Override
public Integer apply(String s) { return Integer.parseInt(s); }
}
3. 泛型方法设计
java
public class Utils {
// 类型参数在返回值前声明
public static <T> T identity(T obj) { return obj; }
// 多类型参数示例
public static <K, V> Map<K, V> createMap(K key, V value) {
Map<K, V> map = new HashMap<>();
map.put(key, value);
return map;
}
}
四、高级特性
1. 通配符系统
java
// 无界通配符
public static void printList(List<?> list) {
list.forEach(System.out::println);
}
// 上界通配符(只读)
public static double sumNumbers(List<? extends Number> numbers) {
return numbers.stream().mapToDouble(Number::doubleValue).sum();
}
// 下界通配符(只写)
public static void addIntegers(List<? super Integer> list) {
list.add(42);
}
2. 类型边界约束
java
// 多边界约束(类必须在前)
public class Calculator<T extends Number & Comparable<T>> {
public T max(T a, T b) { return a.compareTo(b) > 0 ? a : b; }
}
3. 反射操作
java
public class ReflectionDemo {
public static void main(String[] args) throws Exception {
Method method = MyClass.class.getMethod("process", List.class);
// 获取泛型参数类型
Type[] genericParams = method.getGenericParameterTypes();
ParameterizedType pType = (ParameterizedType) genericParams[0];
System.out.println(pType.getActualTypeArguments()[0]);
// 输出实际类型参数(如String.class)
}
}
class MyClass {
public void process(List<String> list) { ... }
}
五、最佳实践
1. 类型安全设计
java
// 使用有限通配符增强API灵活性
public class Box<T> {
private T value;
public void set(T value) { this.value = value; }
// 接受所有Number子类
public void addAll(List<? extends Number> numbers) { ... }
// 返回确切类型
public T getValue() { return value; }
}
2. 性能优化要点
- 减少不必要的装箱操作
- 预估集合容量避免扩容
- 使用专门类型代替通配符(如用
List<Integer>
代替List<? extends Number>
)
3. 常见陷阱规避
java
// 错误:类型擦除导致编译失败
public static <T> void swap(List<T> list, int i, int j) {
T temp = list.get(i); // 编译期类型安全
list.set(i, list.get(j)); // 运行时实际类型可能不匹配
list.set(j, temp);
}
六、典型应用场景
1. 集合框架
java
// 参数化集合
List<String> list = new ArrayList<>();
list.add("Hello"); // 编译期检查
String s = list.get(0); // 无需强制转换
// 映射类型
Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 95);
2. 数据结构实现
java
public class Node<T> {
private T data;
private Node<T> next;
public Node(T data) { this.data = data; }
public void link(Node<? extends T> node) { next = node; }
}
3. 流式处理
java
List<String> words = Arrays.asList("Java", "Generics");
words.stream()
.map(String::toUpperCase)
.filter(s -> s.startsWith("G"))
.findFirst();
七、演进历史
- Java 5:首次引入泛型
- Java 7:钻石操作符简化语法
- Java 8:Lambda表达式与泛型结合
- Java 10:局部变量类型推断(var关键字)
通过掌握这些核心知识体系,开发者可以更精准地运用泛型提升代码质量,同时避免常见陷阱。建议结合JEP文档和OpenJDK源码进行深入学习。