泛型(Generics)

Java中的泛型(Generics)是JDK 5引入的一种特性,它使得类、接口和方法能够以一种类型参数化的方式进行定义和使用。泛型的主要目的是增强代码的类型安全性和可读性,同时减少类型转换(cast)操作。

泛型的基本概念

泛型允许我们在类、接口和方法中定义和使用参数化类型,即用一个占位符(类型参数)来表示实际类型。在实际使用时,具体类型会替换这些类型参数。

泛型类

定义一个带有类型参数的类:

public class Box<T> {
    private T content;

    public void setContent(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

使用泛型类时指定具体类型:

public class Main {
    public static void main(String[] args) {
        Box<String> stringBox = new Box<>();
        stringBox.setContent("Hello");
        String content = stringBox.getContent();
        System.out.println(content);  // 输出: Hello

        Box<Integer> intBox = new Box<>();
        intBox.setContent(123);
        int number = intBox.getContent();
        System.out.println(number);  // 输出: 123
    }
}

泛型接口

定义一个带有类型参数的接口:

public interface Container<T> {
    void add(T item);
    T get(int index);
}

实现泛型接口时指定具体类型:

public class StringContainer implements Container<String> {
    private List<String> items = new ArrayList<>();

    @Override
    public void add(String item) {
        items.add(item);
    }

    @Override
    public String get(int index) {
        return items.get(index);
    }
}

泛型方法

定义一个带有类型参数的方法:

public class Util {
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element);
        }
    }
}

使用泛型方法:

public class Main {
    public static void main(String[] args) {
        Integer[] intArray = {1, 2, 3, 4};
        String[] stringArray = {"Hello", "World"};

        Util.printArray(intArray);  // 输出: 1 2 3 4
        Util.printArray(stringArray);  // 输出: Hello World
    }
}

泛型的高级特性

通配符

Java泛型中的通配符用于表示不确定的类型,可以用在类和方法的参数中。

  1. 无界通配符 (<?>)
    用于表示任意类型。
public static void printList(List<?> list) {
    for (Object elem : list) {
        System.out.println(elem);
    }
}
  1. 有界通配符(上界) (<? extends T>)
    用于表示某个类型的子类型。
public static void printNumbers(List<? extends Number> list) {
    for (Number number : list) {
        System.out.println(number);
    }
}
  1. 有界通配符(下界) (<? super T>)
    用于表示某个类型的父类型。
public static void addNumber(List<? super Integer> list) {
    list.add(1);  // 允许添加Integer或其子类类型的对象
}

泛型类型擦除

在Java中,泛型是在编译时处理的,编译后所有的泛型信息都会被擦除,这个过程被称为类型擦除(Type Erasure)。类型擦除会将泛型类型替换为其限定类型(通常是Object),并插入类型转换以保持类型安全。

例如,以下泛型类:

public class Box<T> {
    private T content;

    public void setContent(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

在编译后,大致会变成:

public class Box {
    private Object content;

    public void setContent(Object content) {
        this.content = content;
    }

    public Object getContent() {
        return content;
    }
}

泛型的限制

由于类型擦除的存在,泛型在Java中有一些限制:

  1. 不能使用基本类型:泛型类型参数不能是基本类型(如intchar等),只能使用包装类型(如IntegerCharacter等)。
  2. 运行时类型查询:在运行时,无法获得泛型类型参数的信息,因此不能使用instanceofgetClass来检查泛型类型。
  3. 静态上下文中不能使用泛型类型参数:泛型类型参数不能用于静态变量、静态方法或静态代码块中。
  4. 不能创建泛型数组:例如new T[10]是不允许的,因为在运行时无法确定类型T

泛型的使用场景

泛型广泛应用于集合框架(如List<T>Map<K, V>等),使得代码更加类型安全,并提高了代码的重用性和可读性。

通过了解和使用Java中的泛型,可以编写更为灵活、安全和可维护的代码。

posted @ 2024-05-14 09:54  xingduo  阅读(23)  评论(0编辑  收藏  举报