泛型通配符
1.什么是类型通配符
类型通配符一般是使用"?"代替具体的类型实参。
所以,类型通配符是类型实参,而不是类型形参。
如何理解这里说的实参呢,因为泛型是将类型参数化了,所以类型通配符是类型实参
2.类型通配符的上限
语法:
类/接口<? extends 实参类型>
要求该泛型的类型,只能是实参类型,或实参类型的子类类型。
规定参数继承自 实参类型
上限通配符,集合 不能填充元素
3.类型通配符的下限
语法:
类/接口<? super 实参类型>
要求该泛型的类型,只能是实参类型,或实参类型的父类类型。
下限通配符,集合 可以填充元素
代码示例
public class Box<E> {
private E first;
public E getFirst() {
return first;
}
public void setFirst(E first) {
this.first = first;
}
}
/**
* 通配符:表示任意类型
* @param box
*/
public static void showBox1(Box<?> box){
Object first = box.getFirst();
System.out.println(first);
}
/**
* 上限通配符 规定参数继承自 Number,想想多态
* @param box
*/
public static void showBox(Box<? extends Number> box){
//上限通配符,集合 不能填充元素
Number first = box.getFirst();
System.out.println(first);
}
/**
* 下限通配符 ,规定只能是Number或者Number的父类
* @param box
*/
public static void showBox2(Box<? super Number> box){
//下限通配符,集合 可以填充元素
Object first = box.getFirst();
System.out.println(first);
}
类型擦除
泛型是Java 1.5版本才引进的概念,在这之前是没有泛型的,但是泛型代码能够很好地和之前版本的代码兼容。那是因为,泛型信息只存在于代码编译阶段,在进入JVM之前,与泛型相关的信息会被擦除掉,我们称之为–类型擦除。
1.代码验证
public static void main(String[] args) {
ArrayList<String> strList = new ArrayList<>();
ArrayList<Integer> intList = new ArrayList<>();
System.out.println(strList.getClass().getSimpleName());
System.out.println(intList.getClass().getSimpleName());
//发生 类型擦除了
System.out.println("-------------");
// 使用反射验证
Erasure<Integer> erasure=new Erasure<>();
Field[] declaredFields = erasure.getClass().getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
//private java.lang.Object com.promsing.generics.demo7.Erasure.key
System.out.println(declaredField.getName());
//key
System.out.println(declaredField.getType().getName());
//java.lang.Object
}
}