← 返回首页
JavaSE系列教程(七十八)
发表时间:2020-02-23 15:12:30
讲解Java泛型通配符 ? 与 T 的区别。

简单来说, ? 是个集合,T 是集合中的一个确定的成员。

1.T 代表一种类型

加在类上,例如: class SuperClass{}

加在方法上,例如: public void fn(T[] a, T obj){}

2.?是通配符,泛指所有类型

一般用于定义一个引用变量,这么做的好处是,如下所示,定义一个sup的引用变量,就可以指向多个对象。

SuperClass<?> sup = new SuperClass<String>("lisi");
sup = new SuperClass<People>(new People());
sup = new SuperClass<Animal>(new Animal());

若不用?,用固定的类型的话,则:

SuperClass<String> sup1 = new SuperClass<String>("lisi");
SuperClass<People> sup2 = new SuperClass<People>("lisi");
SuperClass<Animal> sup3 = new SuperClass<Animal>("lisi");

这就是?通配符的好处。 ? extends T 指T类型或T的子类型 ? super T 指T类型或T的父类型

这个两个一般也是和?一样用在定义引用变量中,但是传值范围不一样。 T和?运用的地方有点不同,?是定义在引用变量上,T是类上或方法上。

注意:如果有泛型方法和非泛型方法,都满足条件,会优先执行非泛型方法。

通过下面例子,我们深刻理解,T表示一个具体类型 而?表示一个集合。

public class GenerateDemo {

    public <T> void test(List<T> list,T obj) {

        List list1 =new ArrayList();
        List<Integer> list2 = new ArrayList();
        List<String> list3 =new ArrayList();
        List<?> list4 = new ArrayList();
        List<T> list5 = new ArrayList();

        list2 = list1;//不使用泛型的集合可以赋值给泛型集合。
        list2.add(100);
        //list2 = list3;//泛型集合类型不一致不能赋值。
        list4 = list2;//可以理解为赋值给一个上界集合。
        //list4.add(100); //错误,?表示一个集合,具体类型无法确定,不能添加。
        list4.add(null); //但是可以添加null;
        list4.remove(0); //可以执行删除操作。

        list5 = list;
        list5.add(obj);//因为T现在是确定的一种类型,可以添加

        for(T object: list5){
            System.out.println(object);
        }
    }

    public static void main(String[] args) {
        List<String> list = new ArrayList();
        GenerateDemo demo = new GenerateDemo();
        demo.test(list,"hello,world!");
    }
}

运行结果:
hello,world!

注意:

==List<?>这个写法非常坑。因为,这时候通配符会捕获具体的String类型,但编译器不叫它String,而是起个临时的代号,比如”CAP#1“。所以以后再也不能往list里添加任何元素,包括String。唯一能添加的就是null。==