泛型的出现
在没有泛型的年代,ArrayList这些集合类可以存放所有类型的对象,都是以object的方式存储,取用的时候,需要一次强制转换,这是一个风险操作,会出现ClassCastExcetion,泛型的出现就是解决这个问题的
泛型的作用
1.编译时类型检查 2.运行时自动转型
怎么使用呢?
在类上定义和使用
public interface Shop<T>{
T buy();
float refund(T item);//退货
}
在方法上定义和使用
public <T> T get(T t){
return t;
}
泛型的继承(泛型类型实例化了)
public interface Shop<T>{
T buy();
float refund(T item);//退货
}
public AShop implements Shop<Apple>{
Apple buy();
float refund(Apple apple);
}
泛型的继承(传递,但并不实例化)
public interface ReparableShop<T> extends Shop<T>{//ps:泛型是个记号,代表这边有需要实例化的类型,需要后续填充类型
void repare(T item);
} //T的作用范围只有本类
多个泛型,多个需要实例化类型的泛型
public interface ReparableShop<T,C> extends Shop<T>{//ps:泛型是个记号,代表这边有需要实例化的类型,需要后续填充类型
void repare(T item);
C get(String name,int id);
}
如何实例化
class SimpleShop implements ReparableShop<Apple,ChinaUnicom>{
}//实例化泛型,放在基类后面
控制泛型的范围(上限,父类指定)
public interface ReparableShop<T,C extends Sim & Activity>{//Sim可为接口,也可以是类,&可限定多个上限
void repare(T item);
C get(String name,int id); }
泛型的PECS
Producer extends Customer super记住super可写,extends可读
ArrayList<Fruits> fruits = new ArrayList<Apple>();(❌错误)
当放入香蕉时,就不符合,左边的条件宽,会导致插入协议不符合条件的元素
ArrayList<? extends Fruits> fruits = new ArrayList<Apple>();//不能用add
编译不报错,但所有的类型方法都会执行出错,因为类型未确定,而时间的list类型又确定了,导致无法添加元素 不过这种做法是有对于的需求的,如下图,有一个现成的list,计算它的重量,但副作用是,无法编辑元素或无法使用有类型参与的方法
ArrayList<? super Apple> fruits = new ArrayList<Fruits>();//不能用get 也可以编译通过,这是设置下界,在方法传递参数的时候可以使用
? super Apple:表示能接受我Apple类型
? extends Fruits:继承
泛型的擦除
怎么发现的:编译成class文件之后,再反编译回来就可以看到,或者直接使用ASM bytecode Viewer工具直接看
为什么?保证兼容性,在Java1.5出现的
都擦了吗?没有,这个比较误导人的地方,它擦了,但没有擦干净,使用的地方全部擦了,但声明的地方被保存到class的signature中,后期还可以通过class.getGenericSuperClass获取到类型,Gson解析中的泛型就是通过生成内部类的方法保存住泛型的
TypeToken<List<String>> token = new ThpeToken<List<String>>(){};
看这里有个匿名内部类