6.2java泛型的高级应用

    技术2026-08-27  7

    (以下不太理解,只是照部分能看懂的搬,不作为参考,只作为笔记)

    擦拭法

    所谓擦拭法是指,虚拟机对泛型其实一无所知,所有的工作都是编译器做的。 例如,我们编写了一个泛型类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(); } }

    泛型继承:子类可以继承父类的泛型类

    extends通配符

    在泛型中,方法传递参数时,若方法传递需要的是一个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中。

    super通配符

    与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原则

    PECS原则:Producer Extends Consumer Super。方便记忆何时使用extends或super

    无限通配符

    无限定通配符<?>很少使用,可以用<T>替换,同时它是所有<T>类型的超类。

    泛型和反射

    部分反射API是泛型,例如:Class,Constructor;可以声明带泛型的数组,但不能直接创建带泛型的数组,必须强制转型;可以通过Array.newInstance(Class, int)创建T[]数组,需要强制转型;
    Processed: 0.008, SQL: 9