返回

泛型世界的分叉小径:extends 与 super 的奥秘

java

通往泛型之巅:探寻 extends 与 super 的边界

前言

在 Java 的广袤世界中,泛型宛如一柄利剑,赋予我们处理各种数据类型的神奇力量。但当我们深入泛型的迷雾时,extends 与 super 这两个关键词犹如两条分叉小径,让人彷徨。本文将带你踏上探索泛型边界的征途,拨开迷雾,揭开它们的神秘面纱。

上边界通配符:extends

extends 犹如一堵屏障,阻挡了超出指定类型及其子类的类型进入我们的泛型集合。换言之,List<? extends Number> 宣告:欢迎 Number 的家族成员,包括 Number 本人,但其他不相干的类型休想染指。

下边界通配符:super

与 extends 相反,super 则敞开大门,允许父类及其本身踏入泛型集合的领地。List<? super Number> 意味:Number 的祖先们,包括 Number,都是座上宾。

实战演练

让我们以一个真实的场景为例,在 removeNegatives 方法中,我们希望从一个泛型列表中剔除所有负数。代码如下:

void removeNegatives(List<? super Number> list) {
    list.stream()
        .filter(x -> x < 0) // 错误:不应移除所有负数
        .forEach(System.out::println); // 错误:未返回或打印结果
}

然而,问题潜伏在暗处:

  • 过滤器错误: x -> x < 0 过滤器将所有负数一网打尽,违背了方法的初衷。
  • 打印错误: 代码返回一个流,却忘了将它转化为列表或打印到控制台。

修正方案

经过一番精雕细琢,我们修正了代码:

void removeNegatives(List<? super Number> list) {
    list.stream()
        .filter(x -> x.doubleValue() >= 0) // 使用 doubleValue() 转换为 double 以进行比较
        .forEach(System.out::println);
}

现在,方法将正确过滤非负数并打印剩余元素。

结论

extends 与 super 是泛型世界的两块基石,掌握它们,才能在泛型之路上畅通无阻。牢记它们的用法:extends 筑起上边界,super 开启下边界。只要理解了它们的本质,你就能自信地驾驭泛型,书写优雅、高效的代码。

常见问题解答

  1. extends 和 super 的区别是什么?

    • extends:指定泛型类型必须是给定类型的子类或该类型本身。
    • super:指定泛型类型必须是给定类型的父类或该类型本身。
  2. 什么时候使用 extends?

    • 当你需要确保泛型类型只能包含给定类型及其子类时。
  3. 什么时候使用 super?

    • 当你需要确保泛型类型可以包含给定类型的父类及其本身时。
  4. 使用泛型有哪些好处?

    • 类型安全:防止不兼容类型进入泛型集合。
    • 代码重用:减少重复代码,提高可维护性。
  5. 在使用泛型时应注意什么?

    • 了解 extends 和 super 的区别。
    • 仔细考虑泛型类型的边界。
    • 避免不必要的泛型化,以免降低代码性能。