一、为什么需要泛型?
1、拥有不同参数类型却有相同的执行流程的方法,需要使用泛型;
2、指定数据类型,可以在编译期间发现类型错误,也不需要进行强制类型转换;
二、泛型类和泛型方法、泛型接口的定义
1、泛型类:
public class A<T>{private T data; public A(T d){} public T getData(){return data;}……}
2、泛型接口:
public interface impl<T>{public T method();}//定义1
class impls<T> implements impl<T>{}//调用1,也是泛型
class impls implements impl<String>{public String method();}//调用2,指定了具体类型
3、泛型方法:(完全独立,不一定要声明在泛型类和泛型接口中)
public <T> T method(T,……) {} <T>泛型方法的标志
class.<String>method();//调用1
class.method();//调用2
三、泛型方法辨析
正确判断泛型方法:<T>开头
四、限定类型
extends:指定泛型类派生于哪个类/接口
public class <T extends c&i>
public <T,V extends c&i> T method(T a,V b);
类和接口混用,类要放在开头,有且只能有1个类
五、泛型中的约束和局限性
1、不能实例化类型变量:new T()//不行
2、静态域和静态方法里不能引用类型变量 private statc T instance;//不行,因为在对象创建的时候,才知道T的具体类型
3、静态方法本身可以是泛型方法
4、泛型只能是类,不能用基础类型,可以用包装类
5、泛型不支持instanceof;
6、泛型的原生类型,类型不会因为T的改变而改变:Test<T>的对象 t(String)和t(Float) 的类型是一样的
7、泛型可以声明数组,却不能new:
Test<T>
Test<Float>[] arrays;//可以
Test<Float>[] arrays = new Test<Float>[10];//不可以
8、泛型类不能够extends Exception和Throwable,try……catch不能够捕获泛型类对象,但可以捕获Throwable。
public <T extends Throwable> void doWork(T x)
{
try{}catch(T x){}//不行
try{} catch(Throwable e) throw T{throw t;}//可以
}
六、泛型类型的继承规则
1、 class A extends B;C<T> C<A>和C<B>没有任何关系,类型之间有继承关系不代表泛型之间有继承关系
2、泛型类可继承自泛型类 class A<T> extends B<T> A<Strnig> a = new B<String>//可以
七、通配符类型
解决继承规则中C<A>和C<B>没有任何关系的局限。
class<T> A;
method(A<? extends/super B>)
? extends B:主要用于安全的访问数据,访问类型B
限定了泛型类型的上限;必须派生B的派生类;调用时增加
get一定是B;set不能用。
? super
限定了泛型类型的下限;必须是B的超类;
设置只能设置本身和子类,返回只能返回Object,主要用于安全的写入数据
八、虚拟机如何实现泛型
类型擦除 T 擦除成Object,T extends A,擦除成A(第一个)。实现接口时,在适当的位置加强制类型转化
重载时,泛型参数的类型不通过。