Java泛型深度解析:从基础语法到高级应用
Java泛型深度解析:从基础语法到高级应用
1. 引言
Java泛型(Generics)是Java SE 5.0引入的一个重要特性,它提供了编译时的类型安全检查,消除了强制类型转换,让代码更加清晰和安全。本文将从基础概念出发,深入探讨泛型的原理、应用和最佳实践。
2. 泛型的基本概念
2.1 什么是泛型
泛型是Java中的一种参数化类型机制,允许在定义类、接口和方法时使用类型参数。这些类型参数在使用时会被具体的类型替换。
2.2 泛型解决的问题
在泛型出现之前,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
使用泛型后:
// 使用泛型的代码
List<String> list = new ArrayList<String>();
list.add("Hello");
// list.add(123); // 编译错误,类型不匹配String str = list.get(0); // 不需要强制类型转换
2.3 泛型的优势
- 类型安全:在编译期进行类型检查,避免运行时的类型转换错误
- 消除强制类型转换:减少代码中的强制类型转换操作
- 代码复用:一套代码可以处理多种类型
- 更好的可读性:代码的意图更加明确
3. 泛型的基本语法
3.1 泛型类
泛型类是指具有一个或多个类型参数的类。
/*** 泛型类示例:简单的容器类* @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 多类型参数
/*** 多类型参数的泛型类* @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;}@Overridepublic 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 泛型接口
/*** 泛型接口示例* @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];}@Overridepublic 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];}@Overridepublic boolean isEmpty() {return size == 0;}@Overridepublic int size() {return size;}private void ensureCapacity() {if (size >= elements.length) {elements = Arrays.copyOf(elements, size * 2);}}
}
3.4 泛型方法
泛型方法可以在普通类中定义,也可以在泛型类中定义。
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
关键字可以限制类型参数的上界。
/*** 数值计算器,只接受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
关键字可以限制类型参数的下界。
/*** 演示下界通配符的使用*/
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 要添加的元素*/@SafeVarargspublic 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 多重边界
类型参数可以有多个上界,使用&
连接。
/*** 演示多重边界的使用*/
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;}@Overridepublic void draw() {System.out.println("Drawing " + name);}@Overridepublic 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)来实现的,在编译时进行类型检查,但在运行时会擦除类型信息。
/*** 演示类型擦除*/
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()); // trueSystem.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
- 有界类型参数:擦除为第一个边界类型
- 泛型方法:类型参数也会被擦除
/*** 类型擦除规则示例*/
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 桥接方法
由于类型擦除,编译器有时需要生成桥接方法来保持多态性。
/*** 演示桥接方法的生成*/
class NumberContainer implements Comparable<NumberContainer> {private int value;public NumberContainer(int value) {this.value = value;}@Overridepublic int compareTo(NumberContainer other) {return Integer.compare(this.value, other.value);}// 编译器会生成桥接方法:// public int compareTo(Object other) {// return compareTo((NumberContainer) other);// }
}
6. 泛型的高级应用
6.1 泛型与反射
/*** 泛型与反射的结合使用*/
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 泛型与工厂模式
/*** 泛型工厂接口* @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");}@Overridepublic void use() {System.out.println("Using " + name);}
}class ConcreteProductB extends Product {public ConcreteProductB() {super("Product B");}@Overridepublic void use() {System.out.println("Using " + name);}
}/*** 具体工厂类*/
class FactoryA implements Factory<ConcreteProductA> {@Overridepublic ConcreteProductA create() {return new ConcreteProductA();}
}class FactoryB implements Factory<ConcreteProductB> {@Overridepublic 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 AproductB.use(); // Using Product B}
}
6.3 泛型与建造者模式
/*** 使用泛型的流式建造者模式* @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 methodspublic String getName() { return name; }public int getAge() { return age; }public String getEmail() { return email; }public String getPhone() { return phone; }public String getAddress() { return address; }@Overridepublic 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();}@Overridepublic 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 泛型数组的创建
/*** 泛型数组的正确创建方式*/
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 泛型的协变和逆变
/*** 协变和逆变示例*/
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:读取数据,使用extendspublic static void copyAnimals(List<Animal> dest, List<? extends Animal> src) {for (Animal animal : src) { // 可以读取dest.add(animal);}}// Consumer:写入数据,使用superpublic static void addDogs(List<? super Dog> list) {list.add(new Dog("Rex")); // 可以写入list.add(new Dog("Max"));}
}
7.3 泛型单例模式
/*** 泛型单例模式* @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 ConfigSystem.out.println(config2); // Application Config(相同实例)}
}
8. 性能考虑
8.1 装箱和拆箱
/*** 泛型与原始类型的性能对比*/
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 命名约定
/*** 泛型类型参数的命名约定*/
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; }}// 函数式接口的命名@FunctionalInterfacepublic interface Converter<INPUT, OUTPUT> {OUTPUT convert(INPUT input);}
}
9.2 API设计原则
/*** 泛型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创建@SafeVarargspublic 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 错误处理
/*** 泛型中的错误处理最佳实践*/
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泛型的各个方面。建议读者在阅读过程中亲自运行和修改示例代码,以加深对泛型概念和应用的理解。