1 无限定通配符 <?>

Generic和Generic可以认为是两个完全没有关联的新类型,两者之间不具有任何继承关系,所以下面的代码会出现编译错误:
image.png
而如果就是希望 printMsg 方法既能接收Generic又能够接收Generic类型,甚至是能够接收传入了任意实参类型的Generic泛型类(如Generic、Generic等),则需要用到泛型通配符?了:

image.png

2 上限通配符 <? extends Number>

为泛型添加上边界,即传入的类型实参必须是指定类型或指定类型的子类。使用extends指定上限通配符
image.png
因为Generic<? extends Number> generic指定了传入的类型实参必须是 Number 类或 Number 类的子类,所以printMsg(genericString);出错,因为 String 不是 Number 的子类

3 下限通配符 <? supper Integer>

和上限通配符类似,下限通配符使用super关键字实现
image.png
因为Generic<? super Integer> generic指定了传入的类型实参必须是 Integer 类或 Integer 类的父类,所以printMsg(genericFloat);和printMsg(genericString);出现编译错误,因为 Float 和 String 都不是 Integer 类的父类

2类型擦除

Java 的泛型只在编译阶段有效,编译过程中正确检验泛型结果后,会将泛型相关信息擦除,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法,即泛型信息不回进入运行时阶段:
image.png
结果返回true,说明虽然编译时Generic和Generic是不同的类型,但因为泛型的类型擦除,所以编译后genericInteger和genericString为相同的类型