(以下不太理解,只是照部分能看懂的搬,不作为参考,只作为笔记)
所谓擦拭法是指,虚拟机对泛型其实一无所知,所有的工作都是编译器做的。 例如,我们编写了一个泛型类Pair,但是虚拟机根本不知道泛型,因此造成了两个局限性:
<T>不能是基本类型,例如int,因为虚拟机看到的实际类型应该是Object类,object类无法持有基本类型。(除了八大基本数据类型外,其余的类型都是Object的子类)无法取得带泛型的class。当创建实例通过反射获取其class时,获取到的都是泛型的类型,例如:public class Pair<T> {}中获取到的是T类型。无法判断带泛型的类型:if (p instanceof Pair<String>) {}原因与上一样。不能实例化T类型: public class Pair<T> { private T first; private T last; public Pair() { // Compile error: first = new T(); last = new T(); } }这样的代码编译后会变成这样:
first = new Object(); last = new Object();创建实例就变成了Object类型 想要成功创建实例,则需要利用反射:
public class Pair<T> { private T first; private T last; public Pair(Class<T> clazz) { first = clazz.newInstance(); last = clazz.newInstance(); } }泛型继承:子类可以继承父类的泛型类
在泛型中,方法传递参数时,若方法传递需要的是一个pair<Number>类型,而我们传递过去的是一个pair<Integer>类型的参数,会出现异常。 因此解决此异常需要用到extends通配符,向上转型 如下demo:
public static void main(String[] args) { Pair<Integer> p = new Pair<>(123, 456); int n = add(p); System.out.println(n); } static int add(Pair<? extends Number> p) { Number first = p.getFirst(); Number last = p.getLast(); return first.intValue() + last.intValue(); }可以用extends限定泛型类的类型
public class Pair<T extends Number> { ... }将T限定在Number中。
与extends相反,super通配符是向下转型
public static void main(String[] args) { Pair<Number> p1 = new Pair<>(12.3, 4.56); Pair<Integer> p2 = new Pair<>(123, 456); setSame(p1, 100); setSame(p2, 200); System.out.println(p1.getFirst() + ", " + p1.getLast()); System.out.println(p2.getFirst() + ", " + p2.getLast()); } static void setSame(Pair<? super Integer> p, Integer n) { p.setFirst(n); p.setLast(n); }使用<? super Integer>通配符作为方法参数,表示方法内部代码对于参数只能写,不能读。 二者对比:
<? extends T>允许调用读方法T get()获取T的引用,但不允许调用写方法set(T)传入T的引用(传入null除外); <? super T>允许调用写方法set(T)传入T的引用,但不允许调用读方法T get()获取T的引用(获取Object除外)。PECS原则:Producer Extends Consumer Super。方便记忆何时使用extends或super
无限定通配符<?>很少使用,可以用<T>替换,同时它是所有<T>类型的超类。
