泛型的概念
所谓泛型, 就是允许在定义类、 接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型或者是构造器参数类型(注意是为了让属性或方法或构造器类型变得可替换)。 这个类型参数将在使用时(例如,继承或实现这个接口, 用这个类型声明变量、 创建对象时) 确定(即传入实际的类型参数, 也称为类型实参)。
JDK7新特性:类型推断
▲泛型的类型不能为基本数据类型
集合中的泛型
JDK1.5改写了集合框架中的全部接口和类, 为这些接口、 类增加了泛型支持,从而可以在声明集合变量、 创建集合对象时传入类型实参。
▲在指明完泛型后,在内部结构(方法、构造器、属性等)中使用到泛型的位置,都要明确指明其类型。
自定义泛型结构(泛型类,泛型接口,泛型方法)
自定义泛型类:
写法:interface List<T> 和 class GenTest<K,V>,其中, T,K,V不代表值,而是表示类型。 这里使用任意字母都可以。常用T表示,是Type的缩写。
注意点:
1、泛型类内部定义的构造器如下:public GenericClass(){},而下面是错误的:public GenericClass<E>(){}
但是在实例化的时候,构造器后要带上尖括号。
2、泛型不同的引用不能相互赋值。ArrayList<String>和ArrayList<Integer>的两种实例化对象不能互相赋值。
3、泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理。
经验: 泛型要使用一路都用。要不用,一路都不要用。
4、泛型类内部的静态方法中不能使用泛型。
5、异常类不能作为泛型类。
6、在对数组结构使用泛型时
7、父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:
子类不保留父类泛型也没有自己新的泛型:
子类不保留父类泛型但是有自己新的泛型:
子类保留父类泛型但没有自己新的泛型:
子类保留父类泛型也有自己新的泛型:
结论:子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自己的泛型。
自定义泛型方法:
方法也可以被泛型化,不管此时定义在其中的类是不是泛型类。 在泛型方法中可以定义泛型参数(该泛型参数和类的无关),此时,参数的类型就是传入数据的类型。
泛型方法的格式:
[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常
▲泛型方法可以是静态的,为什么:
泛型在继承方面的体现
类A是类B的父类,但是M<A>和M<B>没有子父类关系,二者是并列的。
类C是类D的父类,那么C<N>也是D<N>的父类。
通配符的使用
通配符一般只能用在方法参数中,不能用在泛型方法,类的泛型声明,泛型类的实例化中。
类A是类B的父类,但是M<A>和M<B>没有子父类关系,二者是并列的。但二者有共同父类M<?>。
▲对通配符父类M<?>而言,其实例对象不能执行添加操作,但是允许读取数据,读出来的数据类型为Object。
有限制条件的通配符在方法参数中使用时:
M<? extends A>:不能添加数据,因为要保证整个“小于等于A类型”这个范围都是所添加数据类型的父类,显然是不可能的。可以读取数据,读出来的数据类型最小也得为A。
M<? super B>:可以添加数据,只用保证整个“大于等于B类型”这个范围都是所添加数据类型的父类就可以。也可以读取数据,读出来的数据类型最小也得为Object。