通俗易懂理解泛型

将通过一个故事来解释 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 泛型想象成 "类型安全的容器",就像快递公司的标签系统一样,在编译时就确保类型正确,让代码更加健壮和易读。

相关推荐
tangweiguo030519877 分钟前
Kotlin 实现 Android 网络状态检测工具类
android·网络·kotlin
nvvas1 小时前
Android Studio JAVA开发按钮跳转功能
android·java·android studio
怪兽20141 小时前
Android多进程通信机制
android·面试
叶羽西2 小时前
Android CarService调试操作
android
千里马-horse2 小时前
在android中 spdlog库的log如何在控制台上输出
android·c++·spdlog
Zender Han2 小时前
《从零搭建现代 Android 模块化架构项目(2025 最新实践)》
android·架构
Digitally3 小时前
如何从电脑上卸载安卓应用程序
android·电脑
Mr YiRan3 小时前
多线程性能优化基础
android·java·开发语言·性能优化
liyi_hz20083 小时前
O2OA (翱途)开发平台新版本发布预告:架构升级、性能跃迁、功能全面进化
android·java·javascript·开源软件
Huangyi3 小时前
第一节:Flow的基础知识
android·前端·kotlin