Java泛型详解:从入门到精通

发布于:2025-03-31 ⋅ 阅读:(21) ⋅ 点赞:(0)

Java泛型详解:从入门到精通

1. 前言

Java泛型(Generics)是JDK 5引入的一项重要特性,它允许在类、接口和方法中使用类型参数,从而提高代码的类型安全性复用性。本文将详细介绍泛型的基本概念、使用方法、通配符、类型擦除机制以及实际应用场景,帮助你彻底掌握Java泛型。


2. 泛型的基本概念

泛型的本质是参数化类型,即在定义类、接口或方法时,使用一个占位符(如TEKV等)表示类型,等到使用时再指定具体的类型。

2.1 泛型的主要优点

  1. 类型安全:编译时检查类型,避免运行时ClassCastException
  2. 消除强制类型转换:减少代码冗余,提高可读性。
  3. 代码复用:可以编写更通用的算法和数据结构。

3. 泛型的基本使用

3.1 泛型类

泛型类在类名后使用<T>定义类型参数:

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 str = stringBox.get(); // 无需强制转换

3.2 泛型方法

泛型方法在方法返回类型前使用<T>定义类型参数:

public <T> void printArray(T[] array) {
    for (T element : array) {
        System.out.println(element);
    }
}

使用示例:

Integer[] intArray = {1, 2, 3};
String[] strArray = {"A", "B", "C"};
printArray(intArray); // 自动推断类型为Integer
printArray(strArray); // 自动推断类型为String

3.3 泛型接口

泛型接口在接口名后使用<T>定义类型参数:

public interface List<E> {
    void add(E e);
    E get(int index);
}

实现示例:

public class ArrayList<E> implements List<E> {
    private E[] elements;
    // 实现 add 和 get 方法
}

4. 类型通配符

Java泛型提供了通配符?来处理未知类型:

  • List<?>:表示未知类型的列表(可以是任何类型)。
  • List<? extends Number>:表示Number或其子类型的列表(上界通配符)。
  • List<? super Integer>:表示Integer或其父类型的列表(下界通配符)。

4.1 PECS原则(Producer Extends, Consumer Super)

  • Producer Extends(生产者用extends):如果只是从集合中读取数据,使用? extends T
  • Consumer Super(消费者用super):如果只是向集合中写入数据,使用? super T

示例:

// 生产者:只读取数据
public static double sum(List<? extends Number> list) {
    double sum = 0;
    for (Number num : list) {
        sum += num.doubleValue();
    }
    return sum;
}

// 消费者:只写入数据
public static void addNumbers(List<? super Integer> list) {
    list.add(1);
    list.add(2);
}

5. 泛型的限制

  1. 不能使用基本类型List<int> 非法,必须用 List<Integer>
  2. 不能实例化类型参数new T() 非法。
  3. 不能声明静态泛型变量:因为静态成员属于类,而非实例。
  4. 不能对泛型类型使用instanceof:如 if (obj instanceof List<String>) 非法。
  5. 不能创建泛型数组new T[10] 非法(但可以使用(T[]) new Object[10])。

6. 类型擦除(Type Erasure)

Java泛型在编译后会进行类型擦除,即泛型信息在运行时会被擦除,替换为Object或指定的上界类型。这是为了兼容旧版本Java。

示例:

List<String> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
// 运行时,list1 和 list2 的类型都是 ArrayList

7. 实际应用示例

7.1 泛型类实现键值对

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);
System.out.println(pair.getKey() + ": " + pair.getValue());

7.2 泛型方法实现最大值比较

public static <T extends Comparable<T>> T max(T a, T b) {
    return a.compareTo(b) > 0 ? a : b;
}

使用示例:

Integer maxInt = max(10, 20); // 20
String maxStr = max("apple", "orange"); // "orange"

8. 总结

特性 说明
泛型类 class Box<T> { ... }
泛型方法 <T> void print(T t) { ... }
泛型接口 interface List<E> { ... }
上界通配符 List<? extends Number>
下界通配符 List<? super Integer>
类型擦除 运行时泛型信息被擦除

泛型是Java中非常强大的特性,合理使用可以大幅提升代码的安全性可维护性。希望本文能帮助你彻底掌握Java泛型!🚀


📌 推荐阅读:

💬 讨论: 你在使用泛型时遇到过哪些问题?欢迎在评论区交流!👇