Java泛型深度解析:从基础语法到高级应用
1. 引言
Java泛型(Generics)是Java SE 5.0引入的一个重要特性,它提供了编译时的类型安全检查,消除了强制类型转换,让代码更加清晰和安全。本文将从基础概念出发,深入探讨泛型的原理、应用和最佳实践。
2. 泛型的基本概念
2.1 什么是泛型
泛型是Java中的一种参数化类型机制,允许在定义类、接口和方法时使用类型参数。这些类型参数在使用时会被具体的类型替换。
2.2 泛型解决的问题
在泛型出现之前,Java集合框架存在以下问题:
java
// Java 5.0 之前的代码
List list = new ArrayList();
list.add("Hello");
list.add(123); // 可以添加任何类型的对象
String str = (String) list.get(0); // 需要强制类型转换
String str2 = (String) list.get(1); // 运行时会抛出ClassCastException
使用泛型后:
java
// 使用泛型的代码
List<String> list = new ArrayList<String>();
list.add("Hello");
// list.add(123); // 编译错误,类型不匹配
String str = list.get(0); // 不需要强制类型转换
2.3 泛型的优势
- 类型安全:在编译期进行类型检查,避免运行时的类型转换错误
- 消除强制类型转换:减少代码中的强制类型转换操作
- 代码复用:一套代码可以处理多种类型
- 更好的可读性:代码的意图更加明确
3. 泛型的基本语法
3.1 泛型类
泛型类是指具有一个或多个类型参数的类。
java
/**
* 泛型类示例:简单的容器类
* @param <T> 类型参数,可以是任何类型
*/
public class Container<T> {
private T data;
public Container(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
/**
* 泛型方法示例
* @param newData 新的数据
* @return 返回旧的数据
*/
public T updateData(T newData) {
T oldData = this.data;
this.data = newData;
return oldData;
}
}
// 使用示例
Container<String> stringContainer = new Container<>("Hello");
String data = stringContainer.getData(); // 不需要强制转换
Container<Integer> intContainer = new Container<>(42);
Integer number = intContainer.getData();
3.2 多类型参数
java
/**
* 多类型参数的泛型类
* @param <K> 键的类型
* @param <V> 值的类型
*/
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
@Override
public String toString() {
return "Pair{" + "key=" + key + ", value=" + value + '}';
}
}
// 使用示例
Pair<String, Integer> pair = new Pair<>("age", 25);
System.out.println(pair); // 输出:Pair{key=age, value=25}
3.3 泛型接口
java
/**
* 泛型接口示例
* @param <T> 元素类型
*/
public interface Stack<T> {
void push(T item);
T pop();
T peek();
boolean isEmpty();
int size();
}
/**
* 实现泛型接口
*/
public class ArrayStack<T> implements Stack<T> {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_CAPACITY = 10;
public ArrayStack() {
elements = new Object[DEFAULT_CAPACITY];
}
@Override
public void push(T item) {
ensureCapacity();
elements[size++] = item;
}
@Override
@SuppressWarnings("unchecked")
public T pop() {
if (isEmpty()) {
throw new RuntimeException("Stack is empty");
}
T item = (T) elements[--size];
elements[size] = null; // 避免内存泄漏
return item;
}
@Override
@SuppressWarnings("unchecked")
public T peek() {
if (isEmpty()) {
throw new RuntimeException("Stack is empty");
}
return (T) elements[size - 1];
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public int size() {
return size;
}
private void ensureCapacity() {
if (size >= elements.length) {
elements = Arrays.copyOf(elements, size * 2);
}
}
}
3.4 泛型方法
泛型方法可以在普通类中定义,也可以在泛型类中定义。
java
public class GenericMethods {
/**
* 泛型方法:交换数组中两个元素的位置
* @param <T> 数组元素的类型
* @param array 数组
* @param i 第一个索引
* @param j 第二个索引
*/
public static <T> void swap(T[] array, int i, int j) {
if (i != j) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
/**
* 泛型方法:查找数组中指定元素的索引
* @param <T> 数组元素的类型
* @param array 数组
* @param element 要查找的元素
* @return 元素的索引,如果不存在则返回-1
*/
public static <T> int indexOf(T[] array, T element) {
for (int i = 0; i < array.length; i++) {
if (Objects.equals(array[i], element)) {
return i;
}
}
return -1;
}
/**
* 泛型方法:将数组转换为List
* @param <T> 数组元素的类型
* @param array 源数组
* @return 包含数组元素的List
*/
public static <T> List<T> arrayToList(T[] array) {
List<T> list = new ArrayList<>();
Collections.addAll(list, array);
return list;
}
}
// 使用示例
String[] names = {"Alice", "Bob", "Charlie"};
GenericMethods.swap(names, 0, 2); // 交换第1个和第3个元素
int index = GenericMethods.indexOf(names, "Bob"); // 查找Bob的位置
List<String> nameList = GenericMethods.arrayToList(names);
4. 类型边界和约束
4.1 上界通配符(extends)
使用extends
关键字可以限制类型参数的上界。
java
/**
* 数值计算器,只接受Number及其子类
*/
public class NumberProcessor<T extends Number> {
private T number;
public NumberProcessor(T number) {
this.number = number;
}
public double getDoubleValue() {
return number.doubleValue();
}
public int getIntValue() {
return number.intValue();
}
/**
* 比较两个数值的大小
* @param other 另一个数值
* @return 比较结果
*/
public int compareTo(NumberProcessor<? extends Number> other) {
return Double.compare(this.getDoubleValue(), other.getDoubleValue());
}
}
// 使用示例
NumberProcessor<Integer> intProcessor = new NumberProcessor<>(42);
NumberProcessor<Double> doubleProcessor = new NumberProcessor<>(3.14);
// NumberProcessor<String> stringProcessor = new NumberProcessor<>("hello"); // 编译错误
4.2 下界通配符(super)
使用super
关键字可以限制类型参数的下界。
java
/**
* 演示下界通配符的使用
*/
public class CollectionUtils {
/**
* 将源集合的所有元素复制到目标集合
* @param <T> 元素类型
* @param dest 目标集合(接受T或T的父类型)
* @param src 源集合(T或T的子类型)
*/
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (T item : src) {
dest.add(item);
}
}
/**
* 向集合中添加元素
* @param list 集合(接受T或T的父类型)
* @param elements 要添加的元素
*/
@SafeVarargs
public static <T> void addAll(List<? super T> list, T... elements) {
Collections.addAll(list, elements);
}
}
// 使用示例
List<Number> numbers = new ArrayList<>();
List<Integer> integers = Arrays.asList(1, 2, 3);
CollectionUtils.copy(numbers, integers); // Integer是Number的子类
List<Object> objects = new ArrayList<>();
CollectionUtils.addAll(objects, "hello", 42, 3.14); // Object是所有类的父类
4.3 多重边界
类型参数可以有多个上界,使用&
连接。
java
/**
* 演示多重边界的使用
*/
interface Drawable {
void draw();
}
interface Resizable {
void resize(double factor);
}
class Shape implements Drawable, Resizable {
protected String name;
public Shape(String name) {
this.name = name;
}
@Override
public void draw() {
System.out.println("Drawing " + name);
}
@Override
public void resize(double factor) {
System.out.println("Resizing " + name + " by factor " + factor);
}
}
/**
* 要求类型参数既要继承Shape,又要实现Drawable接口
* @param <T> 类型参数
*/
public class GraphicsProcessor<T extends Shape & Drawable> {
private List<T> shapes = new ArrayList<>();
public void addShape(T shape) {
shapes.add(shape);
}
public void drawAll() {
for (T shape : shapes) {
shape.draw(); // 可以调用draw方法,因为T实现了Drawable
}
}
public void resizeAll(double factor) {
for (T shape : shapes) {
if (shape instanceof Resizable) {
((Resizable) shape).resize(factor);
}
}
}
}
5. 类型擦除机制
5.1 类型擦除的概念
Java泛型是通过类型擦除(Type Erasure)来实现的,在编译时进行类型检查,但在运行时会擦除类型信息。
java
/**
* 演示类型擦除
*/
public class TypeErasureDemo {
public static void demonstrateTypeErasure() {
List<String> stringList = new ArrayList<>();
List<Integer> integerList = new ArrayList<>();
// 在运行时,两个List的类型是相同的
System.out.println(stringList.getClass() == integerList.getClass()); // true
System.out.println(stringList.getClass().getName()); // java.util.ArrayList
// 无法在运行时获取泛型的具体类型
// System.out.println(stringList instanceof List<String>); // 编译错误
System.out.println(stringList instanceof List); // true
}
/**
* 通过反射查看类型擦除
*/
public static void reflectionDemo() throws Exception {
List<String> list = new ArrayList<>();
// 获取Class对象
Class<?> clazz = list.getClass();
// 获取泛型父类
Type genericSuperclass = clazz.getGenericSuperclass();
System.out.println("Generic superclass: " + genericSuperclass);
// 获取所有方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.getName().equals("add")) {
System.out.println("Method: " + method);
Type[] paramTypes = method.getGenericParameterTypes();
for (Type paramType : paramTypes) {
System.out.println("Parameter type: " + paramType);
}
}
}
}
}
5.2 类型擦除的规则
- 无界类型参数:擦除为Object
- 有界类型参数:擦除为第一个边界类型
- 泛型方法:类型参数也会被擦除
java
/**
* 类型擦除规则示例
*/
public class ErasureRules<T, U extends Number, V extends Comparable<V>> {
private T t; // 擦除后变成 Object t;
private U u; // 擦除后变成 Number u;
private V v; // 擦除后变成 Comparable v;
public void process(T param) { // 擦除后变成 process(Object param)
// ...
}
public <K> void genericMethod(K param) { // 擦除后变成 genericMethod(Object param)
// ...
}
}
5.3 桥接方法
由于类型擦除,编译器有时需要生成桥接方法来保持多态性。
java
/**
* 演示桥接方法的生成
*/
class NumberContainer implements Comparable<NumberContainer> {
private int value;
public NumberContainer(int value) {
this.value = value;
}
@Override
public int compareTo(NumberContainer other) {
return Integer.compare(this.value, other.value);
}
// 编译器会生成桥接方法:
// public int compareTo(Object other) {
// return compareTo((NumberContainer) other);
// }
}
6. 泛型的高级应用
6.1 泛型与反射
java
/**
* 泛型与反射的结合使用
*/
public class GenericReflection {
/**
* 使用反射创建泛型数组
* @param <T> 数组元素类型
* @param clazz 元素的Class对象
* @param length 数组长度
* @return 创建的数组
*/
@SuppressWarnings("unchecked")
public static <T> T[] createArray(Class<T> clazz, int length) {
return (T[]) Array.newInstance(clazz, length);
}
/**
* 通用的对象复制方法
* @param <T> 对象类型
* @param source 源对象
* @param targetClass 目标类型
* @return 复制的对象
*/
public static <T> T copyObject(Object source, Class<T> targetClass) throws Exception {
T target = targetClass.getDeclaredConstructor().newInstance();
Field[] sourceFields = source.getClass().getDeclaredFields();
Field[] targetFields = targetClass.getDeclaredFields();
Map<String, Field> targetFieldMap = Arrays.stream(targetFields)
.collect(Collectors.toMap(Field::getName, field -> field));
for (Field sourceField : sourceFields) {
Field targetField = targetFieldMap.get(sourceField.getName());
if (targetField != null && targetField.getType() == sourceField.getType()) {
sourceField.setAccessible(true);
targetField.setAccessible(true);
Object value = sourceField.get(source);
targetField.set(target, value);
}
}
return target;
}
}
6.2 泛型与工厂模式
java
/**
* 泛型工厂接口
* @param <T> 产品类型
*/
public interface Factory<T> {
T create();
}
/**
* 抽象产品类
*/
abstract class Product {
protected String name;
public Product(String name) {
this.name = name;
}
public abstract void use();
}
/**
* 具体产品类
*/
class ConcreteProductA extends Product {
public ConcreteProductA() {
super("Product A");
}
@Override
public void use() {
System.out.println("Using " + name);
}
}
class ConcreteProductB extends Product {
public ConcreteProductB() {
super("Product B");
}
@Override
public void use() {
System.out.println("Using " + name);
}
}
/**
* 具体工厂类
*/
class FactoryA implements Factory<ConcreteProductA> {
@Override
public ConcreteProductA create() {
return new ConcreteProductA();
}
}
class FactoryB implements Factory<ConcreteProductB> {
@Override
public ConcreteProductB create() {
return new ConcreteProductB();
}
}
/**
* 使用泛型的工厂管理器
*/
public class GenericFactoryManager {
private Map<Class<?>, Factory<?>> factories = new HashMap<>();
/**
* 注册工厂
* @param <T> 产品类型
* @param productType 产品类型
* @param factory 对应的工厂
*/
public <T> void registerFactory(Class<T> productType, Factory<T> factory) {
factories.put(productType, factory);
}
/**
* 创建产品
* @param <T> 产品类型
* @param productType 产品类型
* @return 创建的产品实例
*/
@SuppressWarnings("unchecked")
public <T> T createProduct(Class<T> productType) {
Factory<T> factory = (Factory<T>) factories.get(productType);
if (factory == null) {
throw new IllegalArgumentException("No factory registered for type: " + productType);
}
return factory.create();
}
// 使用示例
public static void main(String[] args) {
GenericFactoryManager manager = new GenericFactoryManager();
manager.registerFactory(ConcreteProductA.class, new FactoryA());
manager.registerFactory(ConcreteProductB.class, new FactoryB());
ConcreteProductA productA = manager.createProduct(ConcreteProductA.class);
ConcreteProductB productB = manager.createProduct(ConcreteProductB.class);
productA.use(); // Using Product A
productB.use(); // Using Product B
}
}
6.3 泛型与建造者模式
java
/**
* 使用泛型的流式建造者模式
* @param <T> 建造的对象类型
* @param <B> 建造者类型(自己)
*/
public abstract class GenericBuilder<T, B extends GenericBuilder<T, B>> {
/**
* 返回建造者本身,支持方法链调用
* @return 建造者实例
*/
@SuppressWarnings("unchecked")
protected B self() {
return (B) this;
}
/**
* 构建目标对象
* @return 构建的对象
*/
public abstract T build();
}
/**
* 用户实体类
*/
class User {
private final String name;
private final int age;
private final String email;
private final String phone;
private final String address;
protected User(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.email = builder.email;
this.phone = builder.phone;
this.address = builder.address;
}
// Getter methods
public String getName() { return name; }
public int getAge() { return age; }
public String getEmail() { return email; }
public String getPhone() { return phone; }
public String getAddress() { return address; }
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
", phone='" + phone + '\'' +
", address='" + address + '\'' +
'}';
}
/**
* 用户建造者
*/
public static class Builder extends GenericBuilder<User, Builder> {
private String name;
private int age;
private String email;
private String phone;
private String address;
public Builder name(String name) {
this.name = name;
return self();
}
public Builder age(int age) {
this.age = age;
return self();
}
public Builder email(String email) {
this.email = email;
return self();
}
public Builder phone(String phone) {
this.phone = phone;
return self();
}
public Builder address(String address) {
this.address = address;
return self();
}
@Override
public User build() {
if (name == null || name.isEmpty()) {
throw new IllegalStateException("Name is required");
}
return new User(this);
}
}
}
// 使用示例
User user = new User.Builder()
.name("张三")
.age(30)
.email("zhangsan@example.com")
.phone("13800138000")
.address("北京市朝阳区")
.build();
7. 常见问题和注意事项
7.1 泛型数组的创建
java
/**
* 泛型数组的正确创建方式
*/
public class GenericArray<T> {
private Object[] array;
private int size = 0;
@SuppressWarnings("unchecked")
public GenericArray(int capacity) {
// 不能直接创建泛型数组:T[] array = new T[capacity];
// 需要创建Object数组,然后强制转换
array = new Object[capacity];
}
public void add(T element) {
if (size >= array.length) {
resize();
}
array[size++] = element;
}
@SuppressWarnings("unchecked")
public T get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
return (T) array[index];
}
@SuppressWarnings("unchecked")
public T[] toArray(T[] dest) {
if (dest.length < size) {
// 使用反射创建新数组
dest = (T[]) Array.newInstance(dest.getClass().getComponentType(), size);
}
System.arraycopy(array, 0, dest, 0, size);
return dest;
}
private void resize() {
Object[] newArray = new Object[array.length * 2];
System.arraycopy(array, 0, newArray, 0, array.length);
array = newArray;
}
}
7.2 泛型的协变和逆变
java
/**
* 协变和逆变示例
*/
public class VarianceExample {
static class Animal {
String name;
public Animal(String name) { this.name = name; }
}
static class Dog extends Animal {
public Dog(String name) { super(name); }
}
static class Cat extends Animal {
public Cat(String name) { super(name); }
}
public static void varianceDemo() {
// 数组是协变的
Animal[] animals = new Dog[10]; // 合法,但运行时可能出错
// animals[0] = new Cat("Fluffy"); // 运行时会抛出ArrayStoreException
// 泛型集合不是协变的
List<Dog> dogs = new ArrayList<>();
// List<Animal> animals2 = dogs; // 编译错误
// 使用通配符实现协变(只读)
List<? extends Animal> animals3 = dogs; // 协变
Animal animal = animals3.get(0); // 可以读取
// animals3.add(new Dog("Buddy")); // 不能添加,编译错误
// 使用通配符实现逆变(只写)
List<? super Dog> dogSupers = new ArrayList<Animal>(); // 逆变
dogSupers.add(new Dog("Buddy")); // 可以添加Dog
// Dog dog = dogSupers.get(0); // 不能直接获取Dog类型,编译错误
Object obj = dogSupers.get(0); // 只能获取Object类型
}
/**
* PECS原则:Producer Extends, Consumer Super
*/
public static void pecsDemo() {
List<Dog> dogs = Arrays.asList(new Dog("Buddy"), new Dog("Charlie"));
List<Animal> animals = new ArrayList<>();
// Producer用extends:从dogs中读取数据
copyAnimals(animals, dogs);
// Consumer用super:向animals中写入数据
addDogs(animals);
}
// Producer:读取数据,使用extends
public static void copyAnimals(List<Animal> dest, List<? extends Animal> src) {
for (Animal animal : src) { // 可以读取
dest.add(animal);
}
}
// Consumer:写入数据,使用super
public static void addDogs(List<? super Dog> list) {
list.add(new Dog("Rex")); // 可以写入
list.add(new Dog("Max"));
}
}
7.3 泛型单例模式
java
/**
* 泛型单例模式
* @param <T> 单例对象的类型
*/
public class GenericSingleton<T> {
private static final Map<Class<?>, GenericSingleton<?>> instances = new ConcurrentHashMap<>();
private final T instance;
private GenericSingleton(T instance) {
this.instance = instance;
}
/**
* 获取单例实例
* @param <T> 实例类型
* @param clazz 实例的Class对象
* @param supplier 实例创建函数
* @return 单例实例
*/
@SuppressWarnings("unchecked")
public static <T> T getInstance(Class<T> clazz, Supplier<T> supplier) {
GenericSingleton<T> singleton = (GenericSingleton<T>) instances.computeIfAbsent(
clazz,
k -> new GenericSingleton<>(supplier.get())
);
return singleton.instance;
}
/**
* 获取单例实例(使用默认构造函数)
* @param <T> 实例类型
* @param clazz 实例的Class对象
* @return 单例实例
*/
public static <T> T getInstance(Class<T> clazz) {
return getInstance(clazz, () -> {
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("Failed to create instance of " + clazz, e);
}
});
}
// 使用示例
public static class DatabaseConnection {
private String url;
public DatabaseConnection() {
this.url = "jdbc:mysql://localhost:3306/test";
System.out.println("Creating database connection: " + url);
}
public void connect() {
System.out.println("Connecting to: " + url);
}
}
public static void main(String[] args) {
// 获取单例实例
DatabaseConnection conn1 = GenericSingleton.getInstance(DatabaseConnection.class);
DatabaseConnection conn2 = GenericSingleton.getInstance(DatabaseConnection.class);
System.out.println(conn1 == conn2); // true,同一个实例
// 使用自定义创建逻辑
String config = GenericSingleton.getInstance(String.class, () -> "Application Config");
String config2 = GenericSingleton.getInstance(String.class, () -> "Another Config");
System.out.println(config); // Application Config
System.out.println(config2); // Application Config(相同实例)
}
}
8. 性能考虑
8.1 装箱和拆箱
java
/**
* 泛型与原始类型的性能对比
*/
public class PerformanceConsiderations {
/**
* 演示自动装箱/拆箱的性能影响
*/
public static void boxingUnboxingDemo() {
final int SIZE = 1_000_000;
// 使用泛型集合(会发生装箱)
long startTime = System.currentTimeMillis();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < SIZE; i++) {
list.add(i); // 自动装箱
}
int sum1 = 0;
for (Integer num : list) {
sum1 += num; // 自动拆箱
}
long endTime = System.currentTimeMillis();
System.out.println("Generic collection time: " + (endTime - startTime) + "ms");
// 使用原始类型数组(无装箱)
startTime = System.currentTimeMillis();
int[] array = new int[SIZE];
for (int i = 0; i < SIZE; i++) {
array[i] = i;
}
int sum2 = 0;
for (int num : array) {
sum2 += num;
}
endTime = System.currentTimeMillis();
System.out.println("Primitive array time: " + (endTime - startTime) + "ms");
System.out.println("Sum1: " + sum1 + ", Sum2: " + sum2);
}
/**
* 使用专门的原始类型集合避免装箱
*/
public static void primitiveCollectionsDemo() {
// 如果使用第三方库如Eclipse Collections或Trove
// 可以使用专门的原始类型集合,如IntList、DoubleSet等
// 这里演示一个简单的IntList实现
class IntList {
private int[] array;
private int size;
public IntList() {
array = new int[10];
size = 0;
}
public void add(int value) {
if (size >= array.length) {
array = Arrays.copyOf(array, array.length * 2);
}
array[size++] = value;
}
public int get(int index) {
if (index >= size) throw new IndexOutOfBoundsException();
return array[index];
}
public int size() {
return size;
}
}
final int SIZE = 1_000_000;
long startTime = System.currentTimeMillis();
IntList intList = new IntList();
for (int i = 0; i < SIZE; i++) {
intList.add(i); // 无装箱
}
int sum = 0;
for (int i = 0; i < intList.size(); i++) {
sum += intList.get(i); // 无拆箱
}
long endTime = System.currentTimeMillis();
System.out.println("Primitive collection time: " + (endTime - startTime) + "ms");
System.out.println("Sum: " + sum);
}
}
9. 最佳实践
9.1 命名约定
java
/**
* 泛型类型参数的命名约定
*/
public class NamingConventions<T, E, K, V, N extends Number, R> {
// T - Type(类型)
private T value;
// E - Element(元素),常用于集合
private List<E> elements;
// K, V - Key, Value(键值对)
private Map<K, V> keyValuePairs;
// N - Number(数字类型)
private N number;
// R - Return type(返回类型)
public R process() {
// 处理逻辑
return null;
}
// 更具体的命名
public static class Repository<ENTITY, ID> {
public ENTITY findById(ID id) { return null; }
public List<ENTITY> findAll() { return null; }
}
// 函数式接口的命名
@FunctionalInterface
public interface Converter<INPUT, OUTPUT> {
OUTPUT convert(INPUT input);
}
}
9.2 API设计原则
java
/**
* 泛型API设计的最佳实践
*/
public class ApiDesignPractices {
/**
* 原则1:在API中尽可能使用通配符
* 使用PECS原则:Producer Extends, Consumer Super
*/
public static class CollectionProcessor {
// ❌ 不好的设计:过于严格
public static <T> void processBad(List<T> producers, List<T> consumers) {
// 实现
}
// ✅ 好的设计:更灵活
public static <T> void processGood(
List<? extends T> producers, // 生产者,只读
List<? super T> consumers // 消费者,只写
) {
for (T item : producers) {
consumers.add(item);
}
}
}
/**
* 原则2:优先使用泛型方法而不是泛型类
*/
public static class Utilities {
// ✅ 好的设计:泛型方法
public static <T> void swap(T[] array, int i, int j) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
// ❌ 不必要的泛型类
public static class SwapperBad<T> {
public void swap(T[] array, int i, int j) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
/**
* 原则3:合理使用边界限制
*/
public static class BoundedOperations {
// 限制类型,提供更多功能
public static <T extends Comparable<T>> T max(List<T> list) {
if (list.isEmpty()) {
throw new IllegalArgumentException("List is empty");
}
T max = list.get(0);
for (T item : list) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
// 使用多重边界
public static <T extends Cloneable & Serializable> T deepCopy(T original) {
try {
// 序列化深拷贝实现
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(original);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
@SuppressWarnings("unchecked")
T copy = (T) ois.readObject();
return copy;
} catch (Exception e) {
throw new RuntimeException("Deep copy failed", e);
}
}
}
/**
* 原则4:提供类型安全的工厂方法
*/
public static class SafeFactories {
// 类型安全的Map创建
public static <K, V> Map<K, V> newHashMap() {
return new HashMap<>();
}
public static <K, V> Map<K, V> newHashMap(int initialCapacity) {
return new HashMap<>(initialCapacity);
}
// 类型安全的List创建
@SafeVarargs
public static <T> List<T> listOf(T... elements) {
return new ArrayList<>(Arrays.asList(elements));
}
// 使用示例
public static void factoryDemo() {
Map<String, Integer> map = newHashMap(); // 类型推断
List<String> list = listOf("a", "b", "c"); // 类型推断
}
}
}
9.3 错误处理
java
/**
* 泛型中的错误处理最佳实践
*/
public class GenericErrorHandling {
/**
* 泛型异常处理
*/
public static class Result<T, E extends Exception> {
private final T value;
private final E error;
private final boolean isSuccess;
private Result(T value, E error, boolean isSuccess) {
this.value = value;
this.error = error;
this.isSuccess = isSuccess;
}
public static <T, E extends Exception> Result<T, E> success(T value) {
return new Result<>(value, null, true);
}
public static <T, E extends Exception> Result<T, E> failure(E error) {
return new Result<>(null, error, false);
}
public boolean isSuccess() {
return isSuccess;
}
public T getValue() throws E {
if (!isSuccess) {
throw error;
}
return value;
}
public E getError() {
return error;
}
public <U> Result<U, E> map(Function<T, U> mapper) {
if (isSuccess) {
try {
return success(mapper.apply(value));
} catch (Exception e) {
@SuppressWarnings("unchecked")
E castError = (E) e;
return failure(castError);
}
} else {
return failure(error);
}
}
}
/**
* 使用示例
*/
public static void resultDemo() {
Result<Integer, NumberFormatException> result1 = parseInteger("123");
Result<Integer, NumberFormatException> result2 = parseInteger("abc");
if (result1.isSuccess()) {
System.out.println("Parsed: " + result1.getValue());
} else {
System.out.println("Error: " + result1.getError().getMessage());
}
// 使用map进行链式处理
Result<String, NumberFormatException> result3 = result1.map(i -> "Number: " + i);
}
private static Result<Integer, NumberFormatException> parseInteger(String str) {
try {
return Result.success(Integer.parseInt(str));
} catch (NumberFormatException e) {
return Result.failure(e);
}
}
}
10. 总结
Java泛型是一个强大的特性,它提供了编译时的类型安全,消除了强制类型转换,并使代码更加清晰和可维护。通过本文的学习,我们了解了:
核心概念
- 泛型的基本语法和使用方法
- 类型边界和通配符的使用
- 类型擦除机制和其影响
高级应用
- 泛型与反射的结合使用
- 设计模式中的泛型应用
- 协变和逆变的概念
最佳实践
- 合理的命名约定
- API设计原则(PECS原则)
- 性能考虑和优化
注意事项
- 类型擦除的限制
- 泛型数组的创建问题
- 装箱拆箱的性能影响
掌握泛型不仅能写出更安全、更清晰的代码,还能更好地理解和使用Java的集合框架、函数式编程等高级特性。在实际开发中,合理使用泛型能够显著提高代码质量和开发效率。
本文通过大量的代码示例和实际应用场景,深入解析了Java泛型的各个方面。建议读者在阅读过程中亲自运行和修改示例代码,以加深对泛型概念和应用的理解。