【java基础】泛型的通配符(extends,super,?)

基本概念

如果不使用通配符,那么我们在使用了泛型之后就不允许类型参数发生改变了,但是有了通配符就可以更加灵活的控制类型参数,类型参数可以发生改变。下面准备了3个类用于演示

public class A {
    
    

}
public class B extends A {
    
    

}
public class C extends B {
    
    

}

通配符extends

我们使用这个通配符可以限制类型参数是某个类(接口)或者是其子类。

    public static <T extends AutoCloseable> void close(T t) {
    
    
        try {
    
    
            t.close();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

上面代码中我就限定了T是AutoCloseable的实现类,由于是它的实现类,那么AutoCloseable的方法当然也就可以调用了。

如果不需要用到T,那么就可以使用?代替,个数如下

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

上面的List<? extends B>就代表传入的List只能是B类或其子类类型的集合
需要注意的是,对于extends,我们不能够填充元素,也就是写操作

    public static void printList(List<? extends B> list) {
    
    
        list.add(new B());
    }

上面代码会出现错误

在这里插入图片描述

原因就是编译器知道要传入的参数是某个类型的子类型,但不知道具体是哪个子类型

举个例子就是List<? extends B>可以是List<B>和List<C>,假设D为B的子类,那么还可以为List<D>,以此类推,子类是无限制的,所以使用extends肯定就是不能进行写操作了,原因就是子类型无法引用父类型。好比一个List<C>存储一个B元素不合理吧


通配符super

这个通配符可以限制参数类型为某个类或者为其父类

    public static void downLimit(List<? super B> list) {
    
    
        // list.add(new C());
        // list.add(new B());
        for (Object o : list) {
    
    
            System.out.println(o);
        }
    }

List<? super B>就表示传入的类型为B或B的父类的集合。对于super,由于不知道具体传入的是什么,所以就只能使用Object接收了。

对于super,我们可以填充元素

    public static void downLimit(List<? super B> list) {
    
    
        list.add(new C());
        list.add(new B());
    }

对于这种情况,可以理解为List<? super B>可以是List<B>或者List<A>或者其他的父类集合,那么我们我们不管哪种情况,存储B和C都是合理的吧,父类引用子类没有任何问题。

下面就是java核心卷中给出的总结

带有超类型限定的通配符允许你写入一个泛型对象,而带有子类型限定的通配符允许你读取一个泛型对象。

无限定通配符?

下面就来看一个例子分析一下一个Tool类

public class Tool<T> {
    
    

    private T info;

    public T getInfo() {
    
    
        return info;
    }

    public void setInfo(T info) {
    
    
        this.info = info;
    }
}

对于Tool<?>会有以下2个方法

? getInf()
void setInfo(?)

对于getInfo,可以调用,返回值只能赋给Object。对于setInfo,根本不能调用(如果调用只能传入null),因为不知道?是什么。

对于?,通常都是为了避免使用泛型方法。<?>就表示匹配任意类型,和extends和super一起使用分别就表示上限和下限

总结

java核心卷在泛型这章讲的真的是晦涩难懂,如果上面有说错的地方,欢迎大家私信或者评论区指出。

关于泛型的更多知识,参考以下内容

泛型程序设计基础
类型擦除、桥方法、泛型代码和虚拟机
泛型的限制及其继承规则
泛型的通配符(extends,super,?)

猜你喜欢

转载自blog.csdn.net/m0_51545690/article/details/129363949