目录
泛型的定义
1、泛型类就是有一个或多个类型变量的类,泛型方法就是带有类型参数的方法
public class Test<T,E>
{}//类名之后
public static <T> T test()
{}//修饰符之后
2、类型变量的限定
有时类或方法需要对类型变量进行限定,比如这个类型变量需执行compareto()方法,则这个类得继承Comparable接口
public static<T extends Comparable> void test(T t1,T t2)
{
t1.compareto(t2);
}
泛型代码与虚拟机
1、虚拟机没有泛型类型对象,所有的对象都是普通类。
2、类型擦除,本质上来说,编译器把带有泛型的类源码经过编译,生成相应的原始类型,这个原始类型的名子就是去掉类型参数后的泛型类型名。类型变量被擦除,并替换成限定类型。
List<String> list=new ArrayList<>();
List<Integer> list1=new ArrayList<>();
//按照我的理解,这里的两个对象,尽管泛型类型不一样,但是他们都调用的那个擦除后的原始类型。
3、泛型的强转发生在两种情况,其一对方法的调用返回泛型类型的变量,其二当访问一个公共的范型字段时,实际上编译器自动发生了强转
class Pair<T>{
private T first;
private T second;
public T getFirst() {
return first;
}
public void setFirst(T first) {
this.first = first;
}
public T getSecond() {
return second;
}
public void setSecond(T second) {
this.second = second;
}
}
Pair<Employee> buddies=...;
Employee buddy=buddies.getFirst();
//这里在编译后的实质得到了Object o,强转成Employee
4、关于编译器生成桥方法
class D extend Pair<String>{
public void setSecond(String second){...}
}
我们希望用类的多态性,但实际上Pair编译后的方法为:public void setSecond(Object o){...}
产生了冲突,故编译器自动转变为桥方法
class D extend Pair<String>{
public void setSecond(String second){
super.setSecond(second);
}
}//虚拟机的转变
泛型的限制与局限性
1、不能用基本类型实例化类型参数
2、运行时类型查询只适用于原始类型
Pair<String> stringL = new Pair<>();
Pair<Integer>integerL=new Pair<>();
//一个类对应一个Class对象,他们都对应的那个原始类
System.out.println(stringL.getClass()==integerL.getClass());//true
3、不能创建参数化类型的数组,由于擦除,数组没有了类型限制,会发生错误
Pair[] pairs=new Pair<String>[10];//此种写法错误
Pair<String>[] pairs=new Pair[3];//如此写符合语法
4、不能实例化类型变量,new T()等效于new Object()没意义
5、不能有return (T[])new Object[2]; 这里的前置只是样子货,语法上Object[]可以强转为T[],但实质仍为Object[],运行起来会抛出异常;
但由于原类限定型 return (T[])new Comparable[2] ;会抛出异常。
子类的对象可以赋值给父类的引用,父类的对象可以强转为子类的引用,但要强转不抛出异常,需要父类引用指向的本身为子类对象。
6、泛型类的静态上下文中的类型变量无效,静态方法中不能引用类型变量。
泛型类型的继承规则
1、ArrayList<String>,ArrayList<Integer>与ArrayList<Object>没有任何关系,Arraylist是他们的父类
2、ArrayList<String>,ArrayList<Integer>与ArrayList<Object>的父类是List<String>,List<Integer>与List<Object>;List<String>,List<Integer>与List<Object>的父类也是List;ArrayList的父类是List;
3、若A是B的子类,A[]是B[]的子类,则B[] b=new A[2],合法。
通配符
1、通配符有三种表现形式:
ArrayList<? extends Comparable> arrayList=new ArrayList<Integer>();
ArrayList<? super String> arrayList1=new ArrayList<String>();
ArrayList<? > arrayList2=new ArrayList<Object>();
通配符用的地方在泛型类定义好之后,写入那个未知的类型变量E。
2、 ArrayList<? extends Comparable>可以被ArrayList<所有实现Comparable接口的类>赋值
ArrayList<? super String>可以被ArrayList<String或String的超类>赋值
ArrayList<? > 可以被ArrayList<任意类包括Object>赋值
ArrayList<Object>与ArrayList<Integer>没有任何关系,ArrayList<? >的父类是ArrayList