泛型的相关知识

简介: 泛型的相关知识

泛型(Generics)是 Java 中的一种机制,它允许在类或方法中使用参数化类型。通过使用泛型,你可以编写更通用、类型安全且可重用的代码。

泛型的主要目的是在编译时提供类型安全性,并在运行时消除需要进行显式类型转换的需求。它使得我们可以在定义类、接口或方法时使用一个或多个类型参数,这些类型参数可以在使用时被实际的类型替代。

  1. 定义泛型类:
public class Box<T> {
    private T item;
    public T getItem() {
        return item;
    }
    public void setItem(T item) {
        this.item = item;
    }
}
  1. 使用泛型方法:
public <T> T getItem(List<T> list) {
    if (!list.isEmpty()) {
        return list.get(0);
    }
    return null;
}
  1. 限定类型参数:
public <T extends Number> double sum(List<T> list) {
    double total = 0;
    for (T item : list) {
        total += item.doubleValue();
    }
    return total;
}

泛型的上限(Upper Bounds)是指对泛型类型参数进行约束,使其必须是指定的父类或实现的接口。

在 Java 中,可以使用 extends 关键字来指定泛型的上限。通过将类型参数限制为某个特定的父类或接口,可以确保泛型类型参数满足一定的条件。

public class Box<T extends Number> {
    private T item;
    public T getItem() {
        return item;
    }
    public void setItem(T item) {
        this.item = item;
    }
}

在这个示例中,Box 类使用了一个类型参数 T,并通过 extends Number 将其限定为必须是 Number 类或其子类。这样,在实例化 Box 对象时,只能传入 Number 类型或其子类作为类型参数。

通过使用泛型的上限,可以获得以下好处:

  • 在编译时提供更严格的类型检查,避免错误的类型传递。
  • 可以使用父类或接口中定义的方法和属性,提高代码的灵活性和重用性。
  • 在泛型类型参数被限制为某个父类或接口时,可以更清晰地表达代码的意图。

需要注意的是,泛型的上限是包含自身和子类的。例如,Number 的上限为 Number 类型本身,以及其子类如 IntegerDouble 等。

在 Java 中,泛型的下限(Lower Bounds)用于限制泛型类型参数必须是指定的父类或接口的超类

使用下限可以确保泛型类型参数必须是指定的父类或超类,或者是其子类的父类。下限通过关键字 super 来指定。

public void addToList(List<? super Integer> list) {
    list.add(1);
    list.add(2);
    // ...
}

在上面的示例中,addToList 方法有一个泛型参数 List,它表示传入的列表必须是 Integer 类型的超类(包括 Integer 自身和其父类)。

使用泛型下限有以下几点好处:

  • 允许向下转型:通过将泛型类型参数限制为某个父类或超类,可以在泛型方法中将其下属类型添加到列表中。
  • 增加灵活性:可以接受比指定类型更广泛的类型参数,使方法更通用、可重用。
  • 适用于存储操作:泛型下限常用于存储数据的容器,允许容器中存储某个类型及其子类的对象。

需要注意的是,泛型的下限不能用于读取操作,因为不知道具体的类型,只能保证是某个指定类型的父类或超类。

泛型的通配符(Wildcard)是一种特殊的类型参数,可以用来表示未知类型或限定范围内的类型。

在 Java 中,有两种通配符:?? extends。它们用于泛型类、方法或接口中,提供了更灵活的类型处理方式。

  1. ? 通配符表示未知类型。可以用在任何地方,包括泛型类的定义、泛型方法的定义和参数的定义等。例如:
public class Box<T> {
    private T item;
    public void setItem(T item) {
        this.item = item;
    }
    public T getItem() {
        return item;
    }
    public static void processBox(Box<?> box) {
        // 这里可以使用 box,但无法具体知道其类型
    }
}
  1. ? extends 通配符表示类型的上限。可以用于限制泛型参数必须是指定类型或其子类。例如:
public void printList(List<? extends Number> list) {
    for (Number num : list) {
        System.out.println(num);
    }
}
  1. 在上面的例子中,printList 方法接受一个参数 List,表示传入的列表可以是任何扩展自 Number 的类型(包括 Number 自身)。这样可以安全地遍历列表,并对元素进行操作,因为我们知道它们都是 Number 类型或其子类

在上面的例子中,printList 方法接受一个参数 List,表示传入的列表可以是任何扩展自 Number 的类型(包括 Number 自身)。这样可以安全地遍历列表,并对元素进行操作,因为我们知道它们都是 Number 类型或其子类。

使用通配符的好处包括:

  • 增加灵活性:可以处理不同类型的泛型参数,使方法更通用、可重用。
  • 避免类型转换错误:通过限定范围,可以在编译时捕获一些类型错误,提高代码的安全性。

需要注意的是,通配符是用于读取操作的,不能进行写入操作。即不能使用通配符作为方法的参数类型来添加元素到泛型容器中。

E 和通配符 ? 并不相同。

  • E 是一种泛型类型参数的标识符,用于表示某个具体的类型。它在泛型类、泛型方法或接口中被用作占位符,表示可以是任意类型。例如,List 表示一个列表,其中的元素类型为 E。在使用 E 时,需要在实例化泛型类或调用泛型方法时指定具体的类型。
  • ? 是通配符,用于表示未知类型或限定范围内的类型。通配符可以用在泛型类、泛型方法或接口中,用于增加灵活性和安全性。例如,List 表示一个元素类型未知的列表,可以接受任何类型的元素。而 List 表示一个元素类型为 Number 或其子类的列表。

所以,尽管 E? 都与泛型有关,但它们有不同的含义和用法。E 是一个具体的类型占位符,需要在实例化时指定具体的类型,而 ? 是表示未知类型或类型限定的通配符


相关文章
|
7月前
|
Java
|
7月前
|
存储 算法 容器
什么是泛型?
什么是泛型?
31 0
|
7月前
什么是泛型,泛型的具体使用?
什么是泛型,泛型的具体使用?
39 0
|
7月前
|
存储 安全 Java
这还是你认识的泛型吗???!
这还是你认识的泛型吗???!
52 0
|
7月前
|
存储 Java
什么是泛型, 泛型的具体使用?
什么是泛型, 泛型的具体使用?
|
Java
泛型讲解
本章讲解了什么是泛型以及泛型擦除相关的知识点
92 1
|
编译器 C#
C# 泛型
C# 泛型
64 0
|
Java 编译器 API
泛型-详解
泛型-详解
129 0
泛型-详解
|
算法 安全 Java
|
安全 Java 编译器
你了解泛型吗?
面向对象编程中,多态算是一种泛化机制。你可以将方法的参数类型设置为基类,那么该方法就可以接受从这个基类中导出的任何类作为参数,这样的方法将会更具有通用性。此外,如果将方法参数声明为接口,将会更加灵活。