简单来说, ? 是个集合,T 是集合中的一个确定的成员。
1.T 代表一种类型
加在类上,例如: class SuperClass{}
加在方法上,例如:
public
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。==