Java——通配符以及上下限

在 Java 泛型中,通配符 ? 用于表示未知类型,通常用于增强泛型的灵活性。通配符可以与 上限下限 结合使用,进一步限制类型的范围。以下是通配符及其上下限的详细介绍:


一、通配符 ? 的基本用法

通配符 ? 表示未知类型,可以用于泛型类、泛型接口和泛型方法的参数类型。

示例:使用通配符
java 复制代码
// 定义一个方法,接受任意类型的 List
public static void printList(List<?> list) {
    for (Object element : list) {
        System.out.print(element + " ");
    }
    System.out.println();
}

public class Main {
    public static void main(String[] args) {
        List<Integer> intList = Arrays.asList(1, 2, 3);
        List<String> strList = Arrays.asList("A", "B", "C");

        printList(intList); // 输出: 1 2 3
        printList(strList); // 输出: A B C
    }
}

二、通配符的上限(Upper Bound)

通配符的上限通过 ? extends T 表示,限制类型必须是 T 或其子类。

1. 使用场景
  • 用于读取数据(生产者)。
  • 不能写入数据(消费者),因为类型未知。
示例:通配符上限
java 复制代码
// 定义一个方法,接受 Number 或其子类的 List
public static void printNumbers(List<? extends Number> list) {
    for (Number number : list) {
        System.out.print(number + " ");
    }
    System.out.println();
}

public class Main {
    public static void main(String[] args) {
        List<Integer> intList = Arrays.asList(1, 2, 3);
        List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);

        printNumbers(intList); // 输出: 1 2 3
        printNumbers(doubleList); // 输出: 1.1 2.2 3.3

        // 以下代码会报错,因为 String 不是 Number 的子类
        // List<String> strList = Arrays.asList("A", "B", "C");
        // printNumbers(strList);
    }
}

三、通配符的下限(Lower Bound)

通配符的下限通过 ? super T 表示,限制类型必须是 T 或其父类。

1. 使用场景
  • 用于写入数据(消费者)。
  • 不能读取特定类型的数据(生产者),因为类型未知。
示例:通配符下限
java 复制代码
// 定义一个方法,向 List 中添加 Integer 或其父类的元素
public static void addNumbers(List<? super Integer> list) {
    list.add(1);
    list.add(2);
    list.add(3);
}

public class Main {
    public static void main(String[] args) {
        List<Number> numberList = new ArrayList<>();
        addNumbers(numberList); // 添加 Integer 到 Number 列表
        System.out.println(numberList); // 输出: [1, 2, 3]

        List<Object> objectList = new ArrayList<>();
        addNumbers(objectList); // 添加 Integer 到 Object 列表
        System.out.println(objectList); // 输出: [1, 2, 3]

        // 以下代码会报错,因为 String 不是 Integer 的父类
        // List<String> strList = new ArrayList<>();
        // addNumbers(strList);
    }
}

四、通配符的 PECS 原则

PECS(Producer Extends, Consumer Super)是使用通配符的重要原则:

  • Producer Extends :如果泛型是生产者(提供数据),使用 ? extends T
  • Consumer Super :如果泛型是消费者(接受数据),使用 ? super T
示例:PECS 原则
java 复制代码
// 生产者:从源列表复制数据到目标列表
public static <T> void copy(List<? extends T> src, List<? super T> dest) {
    for (T element : src) {
        dest.add(element);
    }
}

public class Main {
    public static void main(String[] args) {
        List<Integer> src = Arrays.asList(1, 2, 3);
        List<Number> dest = new ArrayList<>();
        copy(src, dest); // 复制 Integer 到 Number 列表
        System.out.println(dest); // 输出: [1, 2, 3]
    }
}

五、通配符的注意事项

  1. 不能直接实例化泛型类型
    由于类型擦除,无法直接实例化泛型类型(如 new T())。
  2. 不能用于静态上下文
    类的类型参数不能用于静态方法或静态字段。
  3. 类型擦除
    泛型信息在编译后会被擦除,替换为 Object 或指定的上限类型。

六、总结

  • 通配符 ?:表示未知类型,增强泛型的灵活性。
  • 上限 ? extends T :限制类型必须是 T 或其子类,适用于生产者。
  • 下限 ? super T :限制类型必须是 T 或其父类,适用于消费者。
  • PECS 原则 :生产者用 extends,消费者用 super

通过合理使用通配符及其上下限,可以编写更通用、更灵活的泛型代码。

相关推荐
夜雪一千4 分钟前
Python如何使用XPath定位没有特征的元素?无id、无class通用定位技巧
开发语言·python
Chief_fly14 分钟前
【Windows 下载 ARM64 deb 包 麒麟 ARM 离线安装】
arm开发·windows
艾莉丝努力练剑14 分钟前
【QT:解决问题】Qt5Core.dll:无法定位程序输入点
java·开发语言·qt·学习·面试
流浪00122 分钟前
Python 基础语法(一):常量、变量、输入输出与运算符
开发语言·python
小蒜学长24 分钟前
“喵汪联盟”宠物领养系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·宠物
程序员黑豆25 分钟前
Java字符串常量池完全指南:原理、intern()方法与性能优化最佳实践
java·前端·ai编程
光影少年26 分钟前
react离线缓存、图片缓存方案
开发语言·前端·javascript·react native·react.js·缓存·前端框架
AI人工智能+电脑小能手28 分钟前
大白话说Java设计模式-14-适配器模式(业务实战篇)
java·设计模式·适配器模式·系统兼容·多渠道对接
阿昭L29 分钟前
ZwQuerySystemInformation通过PsLoadedModuleList枚举内核模块
windows·逆向工程·windows内核
SomeB1oody31 分钟前
【RustyML入门】3.7. 循环层
开发语言·后端·机器学习·rust·教程