Skip to content
目录概览

Java 泛型

Java 泛型是 Java 5 中引入的一个重要特性,它提供了编译时类型安全性检查,并且可以在编译时识别错误而不是在运行时。这使得代码更加可靠、安全和易于重构。

什么是泛型?

泛型是在类、接口、方法的声明中使用类型参数来代替具体的类型。通过使用泛型,我们可以将代码从具体的类型中分离出来,使得代码更加通用、灵活且可复用。

泛型的基本使用

泛型通常用来在类中定义一些容器类型,比如 List、Set 等。这些容器可以容纳任何类型的对象,并且可以根据需要进行类型转换。下面是定义一个简单的泛型容器类的代码:

java
public class GenericContainer<T> {
    private T item;

    public void put(T item) {
        this.item = item;
    }

    public T get() {
        return this.item;
    }
}

在这个例子中,我们使用 <T> 来定义一个类型参数。这个类型参数可以被用作类中的其他方法和成员的类型。在 put 方法中,我们使用了泛型类型参数 T 来代表这个方法可以接收任何类型的参数。在 get 方法中,同样地,我们也使用泛型类型参数 T 来表示这个方法可以返回任何类型的值。

在使用泛型容器时,我们可以使用尖括号 <> 来指定它所包含的元素类型。例如:

java
GenericContainer<String> container = new GenericContainer<>();
container.put("Hello, World!");
String str = container.get();
System.out.println(str);

在这个例子中,我们使用 GenericContainer<String> 来实例化一个泛型容器对象。这告诉编译器,我们希望这个容器只能够包含字符串类型的元素。在 put 方法中,我们向容器内添加了一个字符串类型的元素。在 get 方法中,容器返回的值也是一个字符串类型的值。

泛型上限

Java 泛型提供了一个上限限制语法,可以用来指定泛型类或方法的类型参数必须是某个具体类型的子类。这个上限通常用于定义一个类或方法,它只允许处理某些具体类型的对象。

下面是一个例子,这个例子展示了如何将泛型的类型参数限制为某个具体的类或它的子类:

java
public class MyClass<T extends Number> {
    private T number;

    public void setNumber(T number) {
        this.number = number;
    }

    public T getNumber() {
        return this.number;
    }

    public double getDoubleValue() {
        return this.number.doubleValue();
    }
}

在这个例子中,我们使用 <T extends Number> 来指定类型参数必须是 Number 的子类,并用它来定义一个名为 MyClass 的泛型类。在类中,我们声明了一个 number 变量,以及三个方法。setNumber 方法可以接收任何 Number 及其子类类型的值,getNumber 方法可以返回 Number 类型的值,而 getDoubleValue 方法则返回一个 double 类型的值,这个值是从 number 变量获取的。

请注意,我们不能使用任何除 Number 及其子类外的类型来实例化 MyClass,例如 String 类型或 Object 类型。这是由于类的类型参数被限制为 Number 及其子类类型。

泛型通配符

Java 泛型还提供了一种泛型通配符,用来表示某个具体的泛型类型参数,但它的确切类型是未知的。

下面是一个例子,这个例子展示了如何使用通配符来创建一个泛型方法,该泛型方法可以接收任何类型的容器作为参数:

java
public static void printContainer(GenericContainer<?> container) {
    Object item = container.get();
    System.out.println(item.toString());
}

在这个例子中,我们使用了 <?> 来指示参数 container 是一个泛型容器对象,但我们无法确定它的确切类型。在 printContainer 方法中,我们使用了通配符来接收 container 容器对象,由于我们无法确定它的确切类型,因此我们只能使用 Object 类型来接收容器中的元素。

泛型和类型擦除

Java 泛型使用类型擦除来实现泛型,这意味着在编译时,泛型类型被转换为它的原始类型来实现类型安全性。泛型类型参数被擦除为它们的边界,如果边界不存在,就擦除为 Object 类型。

请注意,泛型类型参数擦除并不意味着它们被删除了。它们仍然存在于编译时,并可以在编译时执行类型检查。

总结

Java 泛型是一项强大的特性,它提供了编译时类型安全性检查、代码可读性和可维护性的提升,使得 Java 代码更加可靠、安全和易于重构。泛型常常应用于容器类和算法中,它们可以增强代码的通用性、可复用性和灵活性,在代码编写的不断过程中发挥着至关重要的作用。