美文网首页
Java通配符:灵活使用泛型,提升代码可复用性

Java通配符:灵活使用泛型,提升代码可复用性

作者: 小虎哥的技术博客 | 来源:发表于2023-08-07 08:53 被阅读0次

1. 什么是通配符

通配符是一种泛型技术,它可以接受不同类型的参数,而不需要在编译时指定具体的类型。通配符使用符号 "?" 表示,它表示一个不确定的类型参数,可以用于方法的参数列表,类的定义,方法返回值等。

通配符可以用于以下两种类型:

  • 上界通配符 (Upper Bound Wildcards)
  • 下界通配符 (Lower Bound Wildcards)

2. 上界通配符

上界通配符用于限制泛型参数的类型范围。它可以指定泛型参数必须是某个类型的子类或实现了某个接口。

例如,假设我们要编写一个方法,求一个列表中所有元素的和,那么可以使用上界通配符,限定列表元素类型必须是 Number 或 Number 的子类:

public static double sum(List<? extends Number> list) {...}

这样,我们就可以传入 List<Integer>、List<Double> 等泛型参数进行计算。

因为 list 列表的元素类型都是 Number 或 Number 的子类,所以当我们使用 Number 类型来进行计算时,可以保证类型安全。

Java 常用库中使用上界通配符的方法有:Collections.max、Collections.min 等等。

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

该方法用于计算集合中的最大值,并从泛型集合中确定当前 T 类型参数的范围,即泛型类型参数必须是实现了 Comparable 接口的类。

List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
int max = Collections.max(intList); // 返回 5

上面例子中,intList 中的元素都是 Integer 类型,是 Number 的子类,因此可以直接传递给 Collections.max 方法使用。

3.下界通配符

下界通配符则是用于限制泛型参数的类型范围,但是它与上界通配符的限制方向相反。它可以指定泛型参数必须是某个类型的父类或所实现的某个接口的父接口。

例如,假设我们需要编写一个方法,将一个列表中的元素复制到另一个列表中。然后我们可以使用下界通配符,限定列表元素类型必须是 Object 或 Object 的子类:

public static void copy(List<? super Object> dest, List<Object> src) {...}

这样,我们就可以传入 List<Object>、List<Number>、List<String> 等泛型参数进行复制。

因为 dest 列表的元素类型都是 Object 或 Object 的父类,所以当我们复制 src 到 dest 时,可以保证类型安全。

Java 常用库中使用下界通配符的方法有:Collections.addAll 、Collections.copy 等等。

public static <T> boolean addAll(Collection<? super T> c, T... elements)

该方法用于将指定元素添加到集合中,并且判断添加操作是否成功。其中,c 是泛型集合类型,而 T 是泛型类型参数:

List<Number> numberList = new ArrayList<>();
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
Collections.addAll(numberList, 1, 2.0, 3f);

在上面的例子中,numberList 的类型参数是 Number,它是 Integer 的父类,因此我们可以直接将 List<Integer> 类型的 intList 作为参数传递给 Collections.addAll 方法。

4.无界通配符

如果我们不确定通配符要用到什么类型,或者我们只对类型是任何类的参数感兴趣,此时可以使用无界通配符 <?>。这种情况下,使用者只需传递任意类型的参数即可。

举个例子,假设有一个方法需要将 List 中所有元素都打印出来:

public static void printList(List<?> list) {
    for (Object item : list) {
        System.out.print(item + " ");
    }
}

在上面的例子中,List<?> 中包含了类型为 Object 或其任何子类的项,我们可以将 List<String>、List<Integer>、List<Double> 等任何类型的 List 作为参数传递给此方法。

List<String> strings = Arrays.asList("hello", "world");
List<Integer> integers = Arrays.asList(1, 2, 3);
printList(strings); // 输出 hello world
printList(integers); // 输出 1 2 3

5. 泛型与通配符

当我们谈论Java中的泛型时,我们指的是在定义类或方法时使用类型参数来表示一种“类型的占位符”。通配符则是在使用泛型时,用于表示具体类型的一种方式。

具体来说,泛型是用来增加类型安全性和重用性的一种机制。它允许我们在定义类或方法时指定一种“类型的占位符”,在使用这个类或方法时再指定具体的类型。例如,我们可以定义一个List类,其中的E表示列表中的元素类型,然后在使用这个类时指定具体的类型,如List<Integer>List<String>

而通配符,或者说通配类型,是用来表示一种不确定的或未知的类型。它用问号(?)表示。通配符可以用在泛型类、泛型方法、通配类型参数上,表示可以接受任意类型的参数。

我们可以用一个简单的例子来说明。

假设我们有一个Container类,其中有一个getValue方法用于从容器中获取值。如果我们只是知道这个容器中存储了某种类型的数据,但不知道具体是哪种类型的数据,我们可以使用通配符来表示这个未知的类型。

public class Container<T> {
    private T value;

    public Container(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

现在,我们可以创建一个容器,用一个未知的类型来存储值:

Container<?> container = new Container<>(42);

在这个例子中,<?>就是通配符,表示了一个未知的类型。我们可以接受任何类型的容器对象。但是,我们不能直接修改这个容器中的值,因为我们不知道具体的类型。

使用泛型时,我们可以指定参数的具体类型。例如,我们可以创建一个只能存储整数的容器:

Container<Integer> container = new Container<>(42);

在这个例子中,我们使用了<Integer>这个泛型类型参数,明确告诉编译器我们要存储的是整数类型的值。这样我们不仅可以获取容器中的值,也可以修改容器中的值。

总结来说,泛型是用来定义类或方法时指定类型的一种机制,而通配符是用来表示未知类型或接受任意类型参数的一种方式。泛型让我们可以更加安全和灵活地处理类型,而通配符让我们可以更加通用地处理类型。

相关文章

  • 泛型、型变与投影

    简单泛型 kotlin 对于简单泛型的支持与java类似, 可以通过通配符,提升代码的灵活度 限定型泛型 在编码实...

  • Swift学习笔记--泛型

    泛型 原文链接 泛型代码让你能根据你所定义的要求写出可以用于任何类型的灵活的、可复用的函数。你可以编写出可复用、意...

  • Swift - 泛型

    泛型 泛型代码让你能根据自定义的需求,编写出适用于任意类型的、灵活可复用的函数及类型。你可避免编写重复的代码,而是...

  • Swift底层进阶--014:泛型

    泛型是为Swift编程提供灵活性的一种语法,可以提升代码的复用性和抽象能力例如:Swift的Array和Dicti...

  • "Kotlin"系列: 三、Kotlin协程(上)

    前言 很高兴遇见你~ 在本系列的上一篇中,我们学习了 Kotlin 泛型,使用泛型能使我们的代码具有可复用性,避免...

  • Android 学习(一):Java 泛型

    Java泛型学习 1.0 泛型常用案例 2.0 泛型方法 3.0 泛型类 4.0 通配符 ? 通配符,占位符,标识...

  • Java-API-集合框架(三)-泛型

    泛型的由来和基本使用 泛型的擦除 泛型类的使用 泛型方法的使用 泛型接口 泛型通配符(?) 通配符? 在api中的...

  • Java入门系列08 -- 泛型,集合

    泛型 从Java5开始,引入泛型技术; 泛型:将类型变为参数,提高代码的复用率; 建议使用的类型参数名称有:T:T...

  • Swift 泛型(Generics)

    泛型代码让你能根据你所定义的要求,写出可以用于任何类型的灵活的、可复用的函数。泛型是 Swift 最强大的特性之一...

  • Swift语法 -- [15 - 泛型]

    1.介绍 泛型代码让你能根据你所定义的要求写出可以用于任何类型的灵活的、可复用的函数,泛型是 Swift 最强大的...

网友评论

      本文标题:Java通配符:灵活使用泛型,提升代码可复用性

      本文链接:https://www.haomeiwen.com/subject/oyqgpdtx.html