专业的JAVA编程教程与资源

网站首页 > java教程 正文

泛型中T、?、k、v、extends、super的区别——一篇文章彻底搞懂!

temp10 2025-09-04 18:19:31 java教程 6 ℃ 0 评论

你是否在Java泛型中见过这些符号:T?K/Vextendssuper?它们看似简单,却是泛型的核心!泛型不仅是类型安全的守护者,更是代码复用和灵活性的利器。本文将用代码实战带你彻底搞懂它们!


一、基础符号:TvsK/V

1.T:类型占位符

  • 作用:定义类/方法时表示具体类型的占位符。
  • 场景:泛型类、泛型方法。
// 定义泛型类
public class Box<T> {
    private T data;
    public void setData(T data) { this.data = data; }
    public T getData() { return data; }
}

// 使用
Box<String> stringBox = new Box<>();
stringBox.setData("Hello");
String value = stringBox.getData(); // 直接获取String,无需强转

2.K/V:键值对专用

  • 作用K表示键(Key),V表示值(Value),是T的特殊化。
  • 场景:Map、键值对场景。
public class Pair<K, V> {
    private K key;
    private V value;
    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }
    // getters...
}

// 使用
Pair<String, Integer> user = new Pair<>("age", 30);
String key = user.getKey();   // String类型
Integer value = user.getValue(); // Integer类型

二、通配符?:灵活但受限

1. 基础通配符

  • 作用:表示未知类型,增强灵活性。
  • 限制:只能读(返回Object),不能写(除null外)。
public void printList(List<?> list) {
    for (Object elem : list) {
        System.out.println(elem); // 可读取
    }
    // list.add("error"); // 编译错误!不能写入
}

三、边界限定:extends vs super

1.? extends T:生产者(Producer)

  • 作用:接受T或其子类安全读取数据。
  • 口诀Producer Extends(生产者提供数据)。
// 计算任意Number子类列表的总和
public double sum(List<? extends Number> list) {
    double total = 0;
    for (Number num : list) {
        total += num.doubleValue(); // 安全读取
    }
    return total;
}

// 使用
List<Integer> ints = List.of(1, 2, 3);
sum(ints); // 合法!Integer是Number的子类

2.? super T:消费者(Consumer)

  • 作用:接受T或其父类安全写入数据。
  • 口诀Consumer Super(消费者消费数据)。
// 将数字写入任意Integer父类的列表
public void addNumbers(List<? super Integer> list) {
    for (int i = 1; i <= 3; i++) {
        list.add(i); // 安全写入
    }
}

// 使用
List<Number> numbers = new ArrayList<>();
addNumbers(numbers); // 合法!Number是Integer的父类

四、对比总结:核心区别表

符号

泛型中T、?、k、v、extends、super的区别——一篇文章彻底搞懂!

使用场景

数据方向

示例

T

定义泛型类/方法

读写

Box<T>

K/V

键值对

读写

Pair<K,V>

?

未知类型

只读

List<?>

? extends T

读取数据(生产者)

只读

List<? extends Number>

? super T

写入数据(消费者)

只写

List<? super Integer>


五、实战应用:PECS原则

PECS(Producer-Extends, Consumer-Super) 是泛型使用的黄金法则:

// Java集合框架的copy方法
public static <T> void copy(
    List<? super T> dest, // 消费者:写入目标
    List<? extends T> src  // 生产者:读取源
) {
    for (int i = 0; i < src.size(); i++) {
        dest.add(src.get(i)); // 从src读,向dest写
    }
}

// 使用
List<Integer> src = List.of(1, 2, 3);
List<Number> dest = new ArrayList<>();
Collections.copy(dest, src); // 安全复制!

六、为什么泛型如此重要?

  1. 类型安全:避免ClassCastException
  2. 代码复用:一套逻辑处理多种类型。
  3. 代码清晰:减少强制类型转换。



结语
掌握泛型符号的区别,是写出高质量Java代码的关键!记住:

  • T/K/V用于定义类型;
  • ?提供灵活性;
  • extendssuper通过PECS原则控制数据流向。

下次遇到泛型时,你会自信地说:So easy!

Tags:

猜你喜欢

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表