java 泛型的上界和下界

1.上界

Java 泛型的上界用于限制泛型类型参数必须是某个类型的子类型,通常使用 extends 关键字来表示。下面是一个示例代码,其中 T 的上界是 Comparable<T>,表示 T 必须是实现了 Comparable<T> 接口的类型:

public class Example<T extends Comparable<T>> {
    private T[] array;

    public Example(T[] array) {
        this.array = array;
    }

    public T getMax() {
        T max = array[0];
        for (T item : array) {
            if (item.compareTo(max) > 0) {
                max = item;
            }
        }
        return max;
    }
}

在上面的代码中,Example 类使用了泛型类型参数 T,并通过 extends 关键字指定了 T 的上界是 Comparable<T>,表示 T 必须是实现了 Comparable<T> 接口的类型。在 getMax 方法中,使用了 T 类型的 compareTo 方法,该方法是 Comparable<T> 接口中定义的方法。

通过使用泛型的上界,我们可以在编译时就检查泛型类型参数的类型是否符合要求,从而提高代码的类型安全性和可读性。同时,也可以在泛型类型参数的使用中,直接调用其上界类型中定义的方法和属性。

在 Java 泛型中,还可以使用多个上界,表示泛型类型参数必须同时是多个类型的子类型,这个特性被称为多重上界(Multiple Bounds)。多重上界使用 `&` 连接多个类型,其中第一个类型必须是一个类或者接口,其他的类型必须是接口。例如:


public class Example<T extends Comparable<T> & Serializable> {
    //
}

上面的代码中,`T` 的上界是同时实现了 `Comparable<T>` 和 `Serializable` 接口的类型。

需要注意的是,Java 泛型中的上界和下界都是单向限定的,即只能限定泛型类型参数的上界或下界,而不能同时限定。也就是说,我们不能同时使用 `extends` 和 `super` 关键字来限定一个泛型类型参数。

下面是一个例子,其中定义了一个 `print` 方法,使用了上界通配符 `<? extends Number>` 来限定参数类型:

public class Example {
    public static void print(List<? extends Number> list) {
        for (Number n : list) {
            System.out.print(n + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        List<Integer> intList = Arrays.asList(1, 2, 3);
        List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);
        print(intList);     // 输出:1 2 3
        print(doubleList);  // 输出:1.1 2.2 3.3
    }
}

在上面的代码中,`print` 方法的参数类型是 `List<? extends Number>`,表示该列表中的元素类型必须是 `Number` 类型或其子类型。这样,我们就可以将 `List<Integer>` 和 `List<Double>` 作为参数传递给该方法,因为它们都是 `Number` 的子类型。

2.下界

Java 泛型的下界用于限制泛型类型参数必须是某个类型的父类型,通常使用 `super` 关键字来表示。

下面是一个示例代码,其中 `T` 的下界是 `Number`,表示 `T` 必须是 `Number` 类型或其父类型:

public class Example<T super Number> {
    private T value;

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

    public void setValue(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

在上面的代码中,`Example` 类使用了泛型类型参数 `T`,并通过 `super` 关键字指定了 `T` 的下界是 `Number`,表示 `T` 必须是 `Number` 类型或其父类型。在 `setValue` 方法中,可以将任何类型为 `Number` 的值赋给 `value` 成员变量,包括 `Number`、`Integer`、`Double` 等等。

通过使用泛型的下界,我们可以在编译时就检查泛型类型参数的类型是否符合要求,从而提高代码的类型安全性和可读性。同时,也可以在泛型类型参数的使用中,直接使用其下界类型的方法和属性。

和上界一样,下界也可以和通配符一起使用,例如:

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

public static void main(String[] args) {
    List<Number> numberList = new ArrayList<>();
    addToList(numberList);
    System.out.println(numberList); // 输出:[1, 2, 3]

    List<Object> objectList = new ArrayList<>();
    addToList(objectList);
    System.out.println(objectList); // 输出:[1, 2, 3]
}

上面的代码中,`addToList` 方法的参数类型是 `List<? super Integer>`,表示该列表中的元素类型必须是 `Integer` 的父类型。在方法中,我们可以将 `Integer` 类型的值添加到该列表中。在 `main` 方法中,我们先创建了一个元素类型为 `Number` 的列表和一个元素类型为 `Object` 的列表,然后分别将它们作为参数传递给 `addToList` 方法,并将其输出。可以看到,最终两个列表都包含了元素 `1`、`2`、`3`,说明使用泛型的下界,可以使得方法更加灵活,可以接收更多类型的列表作为参数。

猜你喜欢

转载自blog.csdn.net/qq_55888300/article/details/130520609
今日推荐