Java泛型高级使用

引言

Java泛型是Java SE 5引入的一个重要特性,它使得我们能够在编译时期对代码进行类型检查,从而提高代码的可读性和安全性。在初学者掌握了基本的泛型语法后,我们可以深入研究更高级的泛型技术,以应对更复杂的场景。本文将介绍一些Java泛型的高级使用,包括泛型通配符、泛型上下边界、泛型方法和泛型类的继承等。

泛型通配符

当我们使用泛型时,有时候会遇到无法确定泛型类型的情况,这时就可以使用泛型通配符。泛型通配符用?表示,它可以匹配任何类型。下面是一个使用泛型通配符的示例:

List<?> list = new ArrayList<>();
list.add("Hello"); // 编译错误
list.add(123); // 编译错误
list.add(null); // 可以添加null

在上面的示例中,List<?>表示这个List可以存放任何类型的元素。由于我们无法确定具体的类型,所以无法调用add方法添加元素,只能添加null

泛型通配符还可以用于方法的参数类型和返回类型上。例如,我们有一个打印List元素的方法:

public static void printList(List<?> list) {
    for (Object obj : list) {
        System.out.println(obj);
    }
}

在这个方法中,List<?>表示这个方法可以接受任何类型的List作为参数。通过使用泛型通配符,我们可以实现更灵活的方法定义。

泛型上下边界

泛型上下边界可以限制泛型的类型范围。通常情况下,泛型可以是任意类型,但是有时候我们希望泛型只能是某个特定类型的子类或者父类。我们可以使用泛型上下边界来实现这个限制。下面是一个使用泛型上下边界的示例:

public static <T extends Number> void printNumber(T number) {
    System.out.println(number);
}

public static void main(String[] args) {
    printNumber(123); // 正常调用
    printNumber(3.14); // 正常调用
    printNumber("Hello"); // 编译错误
}

在上面的示例中,<T extends Number>表示泛型T必须是Number类或其子类。通过使用泛型上边界,我们可以限制泛型只能是特定类型的子类。

泛型下边界与泛型上边界相反,它可以限制泛型必须是某个特定类型的父类。下面是一个使用泛型下边界的示例:

public static <T super Integer> void printInteger(T number) {
    System.out.println(number);
}

public static void main(String[] args) {
    printInteger(123); // 正常调用
    printInteger(3.14); // 编译错误
    printInteger("Hello"); // 编译错误
}

在上面的示例中,<T super Integer>表示泛型T必须是Integer类或其父类。通过使用泛型下边界,我们可以限制泛型只能是特定类型的父类。

泛型方法

泛型方法是一种在方法中使用泛型的技术,它可以使得方法的参数和返回类型具备更大的灵活性。下面是一个使用泛型方法的示例:

public static <T> T getFirstElement(List<T> list) {
    if (list.isEmpty()) {
        return null;
    }
    return list.get(0);
}

public static void main(String[] args) {
    List<String> strings = new ArrayList<>();
    strings.add("Java");
    strings.add("Python");
    String first = getFirstElement(strings);
    System.out.println(first); // 输出:Java

    List<Integer> numbers = new ArrayList<>();
    numbers.add(123);
    numbers.add(456);
    Integer firstNumber = getFirstElement(numbers);
    System.out.println(first