Java泛型 #

一、泛型概述 #

1.1 什么是泛型 #

泛型是Java 5引入的特性,允许在定义类、接口、方法时使用类型参数。

1.2 泛型的好处 #

  • 类型安全
  • 消除类型转换
  • 提高代码复用

1.3 泛型示例 #

java
// 没有泛型
List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0);  // 需要类型转换

// 使用泛型
List<String> list2 = new ArrayList<>();
list2.add("Hello");
String s2 = list2.get(0);  // 无需类型转换

二、泛型类 #

2.1 定义泛型类 #

java
public class Box<T> {
    private T value;
    
    public void set(T value) {
        this.value = value;
    }
    
    public T get() {
        return value;
    }
}

// 使用
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get();

Box<Integer> intBox = new Box<>();
intBox.set(100);
Integer num = intBox.get();

2.2 多个类型参数 #

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; }
}

// 使用
Pair<String, Integer> pair = new Pair<>("age", 25);

三、泛型接口 #

3.1 定义泛型接口 #

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;
    }
}

四、泛型方法 #

4.1 定义泛型方法 #

java
public class Utils {
    // 泛型方法
    public static <T> void print(T value) {
        System.out.println(value);
    }
    
    // 多个类型参数
    public static <K, V> void printPair(K key, V value) {
        System.out.println(key + " = " + value);
    }
    
    // 返回泛型
    public static <T> T getFirst(List<T> list) {
        return list.isEmpty() ? null : list.get(0);
    }
}

// 使用
Utils.print("Hello");
Utils.print(100);
Utils.printPair("name", "张三");

4.2 泛型方法与泛型类 #

java
public class Box<T> {
    private T value;
    
    // 泛型类的类型参数T
    public void set(T value) {
        this.value = value;
    }
    
    // 泛型方法,使用新的类型参数E
    public <E> void print(E element) {
        System.out.println(element);
    }
}

五、类型通配符 #

5.1 无界通配符 #

java
public void printList(List<?> list) {
    for (Object item : list) {
        System.out.println(item);
    }
    // list.add("test");  // 错误:不能添加元素
}

5.2 上界通配符 #

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

// 使用
List<Integer> ints = Arrays.asList(1, 2, 3);
List<Double> doubles = Arrays.asList(1.5, 2.5, 3.5);
System.out.println(sum(ints));
System.out.println(sum(doubles));

5.3 下界通配符 #

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

// 使用
List<Number> numbers = new ArrayList<>();
addNumbers(numbers);

List<Object> objects = new ArrayList<>();
addNumbers(objects);

5.4 PECS原则 #

  • Producer Extends:从集合读取(生产)时使用? extends T
  • Consumer Super:向集合写入(消费)时使用? super T
java
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
    for (T item : src) {
        dest.add(item);
    }
}

六、类型擦除 #

6.1 擦除规则 #

java
// 编译前
public class Box<T> {
    private T value;
}

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

6.2 桥方法 #

java
public class StringBox extends Box<String> {
    @Override
    public void set(String value) {
        // ...
    }
    
    // 编译器生成的桥方法
    public void set(Object value) {
        set((String) value);
    }
}

七、泛型限制 #

7.1 不能使用基本类型 #

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

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

7.2 不能实例化类型参数 #

java
public class Box<T> {
    // 错误
    // T value = new T();
    
    // 正确:使用反射
    public T create(Class<T> clazz) throws Exception {
        return clazz.getDeclaredConstructor().newInstance();
    }
}

7.3 不能创建泛型数组 #

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

// 正确
@SuppressWarnings("unchecked")
T[] array = (T[]) new Object[10];

八、总结 #

概念 说明
泛型类 class Box<T>
泛型接口 interface Generator<T>
泛型方法 <T> void method(T t)
上界通配符 ? extends T
下界通配符 ? super T

泛型要点:

  • 泛型提供编译时类型检查
  • 使用PECS原则选择通配符
  • 泛型在运行时被擦除
  • 不能使用基本类型作为类型参数
最后更新:2026-03-26