通俗易懂理解泛型

将通过一个故事来解释 Java 泛型,并结合代码示例说明各种使用场景。

故事场景:快递包裹系统

假设你在一家快递公司工作,负责处理各种类型的包裹。为了让工作更高效,公司引入了一套 "通用容器" 系统(类似于 Java 泛型)。

1. 最初的问题:类型不安全的容器

一开始,公司使用普通的箱子来装所有物品:

java

typescript 复制代码
// 普通箱子,可以装任何东西
class Box {
    private Object item;

    public void put(Object item) {
        this.item = item;
    }

    public Object get() {
        return item;
    }
}

// 使用箱子
Box box = new Box();
box.put("一本书"); // 放入字符串
String book = (String) box.get(); // 需要强制类型转换

问题

  • 箱子可以装任何类型的物品
  • 取出物品时需要手动进行类型转换
  • 如果放错类型(如放入 Integer),运行时会报错(ClassCastException)

2. 引入泛型:类型安全的容器

后来,公司发明了 "类型标签" 箱子,可以在创建时指定能装的物品类型:

java

typescript 复制代码
// 泛型箱子,使用类型参数<T>
class Box<T> {
    private T item;

    public void put(T item) {
        this.item = item;
    }

    public T get() {
        return item;
    }
}

// 使用泛型箱子
Box<String> stringBox = new Box<>();
stringBox.put("一本书"); // 只能放String
String book = stringBox.get(); // 无需强制类型转换

Box<Integer> intBox = new Box<>();
intBox.put(123); // 只能放Integer
Integer number = intBox.get();

优点

  • 在编译时检查类型安全
  • 无需手动类型转换
  • 代码更清晰,可读性更高

泛型的使用场景

1. 泛型类(如 Box)

java

arduino 复制代码
// 自定义泛型类
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<>("年龄", 18);
String key = pair.getKey(); // String类型
Integer value = pair.getValue(); // Integer类型

2. 泛型方法

java

ini 复制代码
// 泛型方法:交换数组中两个元素的位置
public static <T> void swap(T[] array, int i, int j) {
    T temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}

// 使用
String[] names = {"Alice", "Bob", "Charlie"};
swap(names, 0, 2); // 交换names[0]和names[2]

3. 泛型接口

java

typescript 复制代码
// 泛型接口:比较器
interface Comparator<T> {
    int compare(T o1, T o2);
}

// 实现泛型接口
class StringLengthComparator implements Comparator<String> {
    @Override
    public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }
}

4. 上限通配符(? extends T)

假设公司有一个 "电子产品" 分类,所有电子产品都继承自Electronics类:

java

scala 复制代码
class Electronics {}
class Phone extends Electronics {}
class Laptop extends Electronics {}

// 只能存放Electronics及其子类的箱子
void printElectronics(Box<? extends Electronics> box) {
    Electronics item = box.get(); // 安全,因为一定是Electronics类型
    // box.put(new Phone()); // 错误!不能放入任何对象(除了null)
}

用途:读取数据,不写入数据

5. 下限通配符(? super T)

假设公司有一个 "员工" 分类,所有员工都继承自Employee类:

java

scala 复制代码
class Employee {}
class Manager extends Employee {}
class CEO extends Manager {}

// 可以存放Manager及其父类的箱子
void addManager(Box<? super Manager> box) {
    box.put(new Manager()); // 安全,因为Manager及其子类都可以存入
    box.put(new CEO()); // 安全,CEO是Manager的子类
    // Employee emp = box.get(); // 错误!返回类型是? super Manager,无法确定具体类型
}

用途:写入数据,不读取数据

6. 无界通配符(?)

java

csharp 复制代码
// 可以存放任何类型的箱子
void printBox(Box<?> box) {
    Object item = box.get(); // 安全,因为所有类型都是Object的子类
    System.out.println(item);
    // box.put("hello"); // 错误!不能放入任何对象(除了null)
}

7. 泛型擦除

Java 泛型在编译后会被擦除为原始类型:

java

ini 复制代码
Box<String> stringBox = new Box<>();
Box<Integer> intBox = new Box<>();

System.out.println(stringBox.getClass() == intBox.getClass()); // true
// 运行时,两者都是Box类型

总结

泛型的核心思想

  • 将类型参数化,在使用时指定具体类型

  • 提供编译时类型安全检查

  • 避免手动类型转换

  • 增强代码复用性

使用场景

  1. 泛型类:容器类(如 Box、List)

  2. 泛型方法:通用工具方法

  3. 泛型接口:定义通用行为

  4. 上限通配符:读取数据(Producer Extends)

  5. 下限通配符:写入数据(Consumer Super)

  6. 无界通配符:处理任意类型

  7. 泛型擦除:Java 泛型的实现机制

通过这个故事,你可以把 Java 泛型想象成 "类型安全的容器",就像快递公司的标签系统一样,在编译时就确保类型正确,让代码更加健壮和易读。

相关推荐
robotx3 小时前
安卓线程相关
android
消失的旧时光-19433 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon4 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon4 小时前
VSYNC 信号完整流程2
android
dalancon4 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户69371750013845 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android6 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才6 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶7 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle
汪海游龙7 小时前
开源项目 Trending AI 招募 Google Play 内测人员(12 名)
android·github