Skip to content

泛型

泛型是 Java 5 引入的特性,提供了编译时类型安全检测机制。

泛型概述

为什么使用泛型

java
// 不使用泛型(Java 5 之前)
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> list2 = new ArrayList<>();
list2.add("Hello");
// list2.add(123);  // 编译错误,类型安全
String str3 = list2.get(0);  // 无需类型转换

泛型的优点

  • 类型安全:编译时检查类型错误
  • 消除类型转换:无需手动转换类型
  • 代码复用:编写通用代码

泛型类

定义泛型类

java
public class Box<T> {
    private T value;

    public Box(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

// 使用
Box<String> stringBox = new Box<>("Hello");
String str = stringBox.getValue();

Box<Integer> intBox = new Box<>(123);
Integer num = intBox.getValue();

// 菱形语法(Java 7+)
Box<Double> doubleBox = new Box<>(3.14);

多个类型参数

java
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 "(" + key + ", " + value + ")";
    }
}

// 使用
Pair<String, Integer> pair = new Pair<>("年龄", 25);
System.out.println(pair.getKey() + ": " + pair.getValue());

泛型接口

定义泛型接口

java
public interface Generator<T> {
    T generate();
}

// 实现方式1:指定具体类型
public class StringGenerator implements Generator<String> {
    @Override
    public String generate() {
        return "Hello";
    }
}

// 实现方式2:保留泛型
public class GenericGenerator<T> implements Generator<T> {
    @Override
    public T generate() {
        return null;
    }
}

泛型接口示例

java
public interface Repository<T, ID> {
    T findById(ID id);
    void save(T entity);
    void delete(ID id);
    List<T> findAll();
}

public class UserRepository implements Repository<User, Long> {
    @Override
    public User findById(Long id) {
        // 实现查找逻辑
        return null;
    }

    @Override
    public void save(User entity) {
        // 实现保存逻辑
    }

    @Override
    public void delete(Long id) {
        // 实现删除逻辑
    }

    @Override
    public List<User> findAll() {
        // 实现查找所有逻辑
        return null;
    }
}

泛型方法

定义泛型方法

java
public class Utils {
    // 泛型方法
    public static <T> void print(T value) {
        System.out.println(value);
    }

    // 泛型方法返回值
    public static <T> T getFirst(List<T> list) {
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    // 多个类型参数
    public static <K, V> void printPair(K key, V value) {
        System.out.println(key + " = " + value);
    }

    // 泛型方法与可变参数
    @SafeVarargs
    public static <T> List<T> createList(T... elements) {
        List<T> list = new ArrayList<>();
        Collections.addAll(list, elements);
        return list;
    }
}

// 使用
Utils.print("Hello");
Utils.print(123);

String first = Utils.getFirst(Arrays.asList("a", "b", "c"));

Utils.printPair("name", "张三");

List<String> list = Utils.createList("a", "b", "c");

泛型方法与类型推断

java
public class Collections {
    // 空集合
    public static <T> List<T> emptyList() {
        return new ArrayList<>();
    }

    // 类型推断
    List<String> strings = Collections.emptyList();

    // 显式指定类型
    List<Integer> integers = Collections.<Integer>emptyList();
}

类型通配符

无界通配符 ?

java
// 可以接受任何类型
public void printList(List<?> list) {
    for (Object item : list) {
        System.out.println(item);
    }
}

List<String> strings = Arrays.asList("a", "b", "c");
List<Integer> integers = Arrays.asList(1, 2, 3);

printList(strings);
printList(integers);

// 注意:不能添加元素(除了 null)
List<?> list = new ArrayList<String>();
// list.add("hello");  // 编译错误
list.add(null);  // 可以

上界通配符 ? extends T

java
// 接受 T 或 T 的子类
public double sum(List<? extends Number> list) {
    double total = 0;
    for (Number num : list) {
        total += num.doubleValue();
    }
    return total;
}

List<Integer> integers = Arrays.asList(1, 2, 3);
List<Double> doubles = Arrays.asList(1.1, 2.2, 3.3);

System.out.println(sum(integers));  // 6.0
System.out.println(sum(doubles));   // 6.6

// 注意:不能添加元素
List<? extends Number> list = new ArrayList<Integer>();
// list.add(1);  // 编译错误

下界通配符 ? super T

java
// 接受 T 或 T 的父类
public void addNumbers(List<? super Integer> list) {
    list.add(1);
    list.add(2);
    list.add(3);
}

List<Number> numbers = new ArrayList<>();
List<Object> objects = new ArrayList<>();

addNumbers(numbers);
addNumbers(objects);

// 注意:读取时只能得到 Object
List<? super Integer> list = new ArrayList<Number>();
list.add(1);
Object obj = list.get(0);  // 只能是 Object

PECS 原则

Producer Extends, Consumer Super

  • 生产者(只读):使用 ? extends T
  • 消费者(只写):使用 ? super T
java
public static <T> void copy(
        List<? super T> dest,    // 消费者:写入
        List<? extends T> src) { // 生产者:读取
    for (int i = 0; i < src.size(); i++) {
        dest.set(i, src.get(i));
    }
}

List<Integer> src = Arrays.asList(1, 2, 3);
List<Number> dest = new ArrayList<>(Arrays.asList(0, 0, 0));
copy(dest, src);

类型擦除

擦除机制

java
// 泛型类
public class Box<T> {
    private T value;
}

// 编译后(类型擦除)
public class Box {
    private Object value;
}

// 有界类型参数
public class NumberBox<T extends Number> {
    private T value;
}

// 编译后
public class NumberBox {
    private Number value;
}

桥接方法

java
public class StringBox extends Box<String> {
    @Override
    public void setValue(String value) {
        super.setValue(value);
    }
}

// 编译后生成桥接方法
public class StringBox extends Box {
    @Override
    public void setValue(String value) {
        super.setValue(value);
    }

    // 桥接方法
    public void setValue(Object value) {
        setValue((String) value);
    }
}

泛型限制

不能使用基本类型

java
// 错误
// List<int> list = new ArrayList<>();

// 正确:使用包装类
List<Integer> list = new ArrayList<>();

不能实例化类型参数

java
public class Factory<T> {
    // 错误
    // T instance = new T();

    // 正确:使用反射
    public T create(Class<T> clazz) throws Exception {
        return clazz.getDeclaredConstructor().newInstance();
    }
}

不能创建泛型数组

java
// 错误
// T[] array = new T[10];

// 正确:使用 Object 数组或反射
@SuppressWarnings("unchecked")
T[] array = (T[]) new Object[10];

// 或使用 Array.newInstance
T[] array = (T[]) Array.newInstance(clazz, 10);

不能使用泛型类型的静态成员

java
public class Box<T> {
    // 错误
    // private static T value;

    // 错误
    // public static T getValue() { return value; }

    // 正确:静态方法可以使用自己的类型参数
    public static <E> E process(E value) {
        return value;
    }
}

不能抛出或捕获泛型类实例

java
// 错误
// public class MyException<T> extends Exception { }

// 错误
// try { } catch (T e) { }

// 正确:在方法签名中声明
public <T extends Throwable> void throwException(Class<T> clazz) throws T {
    // ...
}

泛型实战

泛型容器

java
public class Container<T> {
    private Map<String, T> map = new HashMap<>();

    public void put(String key, T value) {
        map.put(key, value);
    }

    public T get(String key) {
        return map.get(key);
    }

    public T getOrDefault(String key, T defaultValue) {
        return map.getOrDefault(key, defaultValue);
    }

    public boolean contains(String key) {
        return map.containsKey(key);
    }

    public void remove(String key) {
        map.remove(key);
    }

    public Set<String> keys() {
        return map.keySet();
    }

    public Collection<T> values() {
        return map.values();
    }
}

// 使用
Container<String> container = new Container<>();
container.put("name", "张三");
container.put("city", "北京");
System.out.println(container.get("name"));

泛型工具类

java
public class GenericUtils {

    // 判断是否为空
    public static <T> boolean isEmpty(T[] array) {
        return array == null || array.length == 0;
    }

    // 判断是否为空(集合)
    public static <T> boolean isEmpty(Collection<T> collection) {
        return collection == null || collection.isEmpty();
    }

    // 获取第一个元素
    public static <T> Optional<T> first(List<T> list) {
        if (isEmpty(list)) {
            return Optional.empty();
        }
        return Optional.of(list.get(0));
    }

    // 获取最后一个元素
    public static <T> Optional<T> last(List<T> list) {
        if (isEmpty(list)) {
            return Optional.empty();
        }
        return Optional.of(list.get(list.size() - 1));
    }

    // 数组转列表
    @SafeVarargs
    public static <T> List<T> toList(T... elements) {
        List<T> list = new ArrayList<>();
        Collections.addAll(list, elements);
        return list;
    }

    // 列表转数组
    public static <T> T[] toArray(List<T> list, Class<T> clazz) {
        @SuppressWarnings("unchecked")
        T[] array = (T[]) Array.newInstance(clazz, list.size());
        return list.toArray(array);
    }

    // 过滤
    public static <T> List<T> filter(List<T> list, Predicate<T> predicate) {
        List<T> result = new ArrayList<>();
        for (T item : list) {
            if (predicate.test(item)) {
                result.add(item);
            }
        }
        return result;
    }

    // 映射
    public static <T, R> List<R> map(List<T> list, Function<T, R> mapper) {
        List<R> result = new ArrayList<>();
        for (T item : list) {
            result.add(mapper.apply(item));
        }
        return result;
    }
}

泛型构建器

java
public class Builder<T> {
    private T value;
    private final List<Consumer<T>> operations = new ArrayList<>();

    public Builder<T> with(Consumer<T> operation) {
        operations.add(operation);
        return this;
    }

    public Builder<T> with(T initialValue) {
        this.value = initialValue;
        return this;
    }

    public T build() {
        operations.forEach(op -> op.accept(value));
        return value;
    }

    public static <T> Builder<T> of(T initialValue) {
        return new Builder<T>().with(initialValue);
    }
}

// 使用
class Person {
    String name;
    int age;

    void setName(String name) { this.name = name; }
    void setAge(int age) { this.age = age; }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

Person person = Builder.of(new Person())
    .with(p -> p.setName("张三"))
    .with(p -> p.setAge(25))
    .build();
System.out.println(person);

类型安全的异构容器

java
public class TypeSafeContainer {
    private final Map<Class<?>, Object> map = new HashMap<>();

    public <T> void put(Class<T> type, T instance) {
        map.put(type, instance);
    }

    public <T> T get(Class<T> type) {
        return type.cast(map.get(type));
    }

    public <T> boolean contains(Class<T> type) {
        return map.containsKey(type);
    }
}

// 使用
TypeSafeContainer container = new TypeSafeContainer();
container.put(String.class, "Hello");
container.put(Integer.class, 123);
container.put(Double.class, 3.14);

String str = container.get(String.class);
Integer num = container.get(Integer.class);
Double d = container.get(Double.class);