Java知识体系之-泛型与泛型擦除
#Java泛型与进阶
##什么是泛型
泛型是Java中一种常用的用于解决编译期间的类型转换异常的方式,防止在运行期间出现classCastException。
代码如下:
public class GlmapperGeneric<T> {
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
public static void main(String[] args) {
// do nothing
}
/**
* 不指定类型
*/
public void noSpecifyType(){
GlmapperGeneric glmapperGeneric = new GlmapperGeneric();
glmapperGeneric.set("test");
// 需要强制类型转换
String test = (String) glmapperGeneric.get();
System.out.println(test);
}
/**
* 指定类型
*/
public void specifyType(){
GlmapperGeneric<String> glmapperGeneric = new GlmapperGeneric();
glmapperGeneric.set("test");
// 不需要强制类型转换
String test = glmapperGeneric.get();
System.out.println(test);
}
}
##泛型中的通配符
在泛型中,通常使用的通配符有如下几种:T,E,K,V ? ,这些符号你可以自己指定,但是为了更好的理解,我们通常使用上述作为默认规则。
T:代表指定的Java类型;
E:代表Element;
K和V:用于在Map中存储的key-value;
?:代表不确定的Java类型;
###?通配符
我们先来看一个例子:List<? extend Animals> list = new List();
此时,它表示的意思就是我们的这个list可以传递的就是继承了Animals的子类;
###上届通配符
所谓的上届通配符就是< ? extends E>,代表的意思是传递任意一个E本身或者E的子类都OK。
###下届通配符
所谓的下届通配符就是< ? super E>,代表的意思是传递任意一个是E本身或者E的父类都OK。
private <T> void test(List<? super T> dst, List<T> src){
for (T t : src) {
dst.add(t);
}
}
public static void main(String[] args) {
List<Dog> dogs = new ArrayList<>();
List<Animal> animals = new ArrayList<>();
new Test3().test(animals,dogs);
}
// Dog 是 Animal 的子类
class Dog extends Animal {
}
###?和T的区别
从字面的意思上来看:?代表的是非指定的任意Java类,T代表的是指定的Java类,T只可以继承某个类,而?可以标识父类或者子类:? extend A , ? super A。
##泛型擦除
// 指定泛型为String
List<String> list1 = new ArrayList<>();
// 指定泛型为Integer
List<Integer> list2 = new ArrayList<>();
System.out.println(list1.getClass() == list2.getClass()); // true
在编译时,对于这些已经指定过的泛型,编译器会将它们都清除掉,这样的操作我们叫做泛型擦除。
规则:如果我们给泛型指定了上届,那么在擦除之后,它会指定到上届。否则,它将指定到Object。
##参考地址
https://juejin.im/post/5d5789d26fb9a06ad0056bd9
https://juejin.im/post/5ceba1a2f265da1b95703558