java 为什么上界通配符在下面的示例中起作用

rhfm7lfc  于 2023-06-04  发布在  Java
关注(0)|答案(1)|浏览(428)
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

class A<T> {
    T t;

    public void setT(T t) {
        this.t = t;
    }

    T getT() {
        return t;
    }
}

    public static void print1(A<? extends Animal> obj){
        //obj.setT(new Cat()); //Line 1
        System.out.println(obj.getT().getClass());

    }

    public static void print2(A<? super Animal> obj){
        obj.setT(new Dog()); //Line 2
        System.out.println(obj.getT().getClass());

    }

我理解为什么第1行不能编译,但完全不理解为什么第2行可以编译。
我正在尝试理解Java中的下限和上限通配符

5jdjgkvh

5jdjgkvh1#

在Java泛型中,A<?extends Animal>是一个带有上限的通配符类型声明。这意味着类型参数T可以是Animal的任何子类型(包括Animal本身)。当你有一个带上限的通配符时,它可以确保类型是“只读”的,也就是说你只能检索T类型的值,但不能修改内容。
在print 1方法中,obj用上界通配符A<?扩展Animal>。这意味着您可以调用getT()方法,该方法返回T类型的值(这是Animal的某个子类型),但您不能调用setT()方法,因为T的确切类型未知。编译器无法保证将Cat赋值给T的安全性,因为T可能是Animal的更具体的子类型,例如Dog。
另一方面,A<?super Animal>是一个带有下限的通配符类型的声明。这意味着类型参数T可以是Animal的任何超类型(包括Animal本身)。当您有一个带下限的通配符时,它允许您检索和修改对象的内容。
在print 2方法中,obj是用一个下界通配符A<?super Animal>.这意味着您可以同时调用getT()和setT()方法。setT()方法接受Animal的任何子类型(包括Animal本身),因为任何这样的子类型都是对T的有效赋值(可以是Animal的超类型)。在这种情况下,您可以将Dog分配给T,因为T可以是Dog的超类型(例如,Animal)。

相关问题