一、泛型概述:
1、所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实际的类型参数,也称为类型实参)。
2、从JDK1.5以后,Java引入了“参数化类型(Parameterized type)”的概念,允许我们在创建集合时再指定集合元素的类型,正如:List,这表明该List只能保存字符串类型的对象。
3、JDK1.5改写了集合框架中的全部接口和类,为这些接口、类增加了泛型支持,从而可以在声明集合变量、创建集合对象时传入类型实参。
二、在集合中使用泛型:
1、集合接口或集合类在JDK5.0时都修改为带泛型的结构。
2、在实例化集合类时,可以指明具体的泛型类型
3、指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置都指定为实例化时泛型类型。比如add(E e),实例化以后:add(Integer e)
4、注意点:泛型的类必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换。
5、如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型。
三、泛型在继承性上的体现:
1.假如B是A的一个子类型(或者是子接口),而G是具有泛型声明的类或接口,G<B>并不是G<A>的子类型!
比如:String是Object的子类,但是List<String>并不是List<Object>的子类。
四、通配符的使用:
1.通配符的使用不同于泛型是大写的字母,通配符用?来表示。
比如:List<?>,Map<?>
这个时候,List<?>是List<String>、List<Object>等各种泛型List的父类。
2.读取List<?>的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。
3.写入list中的元素时,不行。因为我们不知道?的元素类型,不能向其中添加对象。唯一例外的是null,它是所有类型的成员,因此可以添加。
五、通配符的限制:
1、通配符指定上限
上限extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即<=
2、 通配符指定下限
下限super:使用时指定的类型不能小于操作的类,即>=
3、举例:
3.1 (无穷小 , Number]
只允许泛型为Number及Number子类的引用调用
3.2[Number , 无穷大)
只允许泛型为Number及Number父类的引用调用
3.3
只允许泛型为实现Comparable接口的实现类的引用调用
4、代码实例:
List<? extend Person> list1 = null; List<? super Person> list2= null;//这里假设有一个Person的子类Student List<Stduent> list3 = new ArrayList<>();//默认 List<Person> list4 = new ArrayList<>(); List<Object> list5 = new ArrayList<>(); list1 = list3; list1 = list4; list1 = list5;//报错,因为list1只可能是Person或Person的子类,无法直接赋值Object list2 = list3;//报错,因为list2只可能是Perison或Peroson的父类,无法赋值给其下的类 list2 = list4; list2 = list5; //读取数据方面: list1 = list3; Person p = List1.get(0);//可以是Object或Person,但不可以是Stduent,因为是<=,虽然类型可以是Stduent,但是声明上只能是Person,以免给的数据类型是Person。 list2 = list4; Object obj = list2.get(0);//只能是Object,因为右边的数据类型是>=Person的,同上,如果是大于Person,而左边声明为Person就会报错,所以只能是Object。