通俗易懂理解泛型

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

相关推荐
高林雨露31 分钟前
RecyclerView中跳转到最后一条item并确保它在可视区域内显示
android
移动开发者1号3 小时前
ReLinker优化So库加载指南
android·kotlin
山野万里__3 小时前
C++与Java内存共享技术:跨平台与跨语言实现指南
android·java·c++·笔记
Huckings3 小时前
Android 性能问题
android
移动开发者1号3 小时前
剖析 Systrace:定位 UI 线程阻塞的终极指南
android·kotlin
移动开发者1号3 小时前
深入解析内存抖动:定位与修复实战(Kotlin版)
android·kotlin
whysqwhw3 小时前
OkHttp深度架构缺陷分析与革命性演进方案
android
Digitally5 小时前
如何将文件从 iPhone 传输到 Android(新指南)
android·ios·iphone
whysqwhw6 小时前
OkHttp深度架构缺陷分析与演进规划
android
用户7093722538516 小时前
Android14 SystemUI NotificationShadeWindowView 加载显示过程
android