欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java泛型探索

程序员文章站 2022-07-14 20:54:51
...

1.关于泛型擦除

public class ErasedType {
    public static void main(String[] args) {
        Class c1 = new ArrayList<Integer>().getClass();
        Class c2 = new ArrayList<String>().getClass();
        System.out.println(c1 == c2);
    }
}

上面代码的输出结果为:

Java泛型探索

class Frop {
}

class Fnorkle {
}

class Quark<Q> {
}

class Particle<POOSITION, MOMENTUM> {
}


public class ErasedType {
    public static void main(String[] args) {
        List<Frop> list = new ArrayList<Frop>();
        Map<Frop, Fnorkle> map = new HashMap<Frop, Fnorkle>();
        Quark<Fnorkle> quark = new Quark<Fnorkle>();
        Particle<Long, Double> particle = new Particle<Long, Double>();
        System.out.println(Arrays.toString(list.getClass().getTypeParameters()));
        System.out.println(Arrays.toString(map.getClass().getTypeParameters()));
        System.out.println(Arrays.toString(quark.getClass().getTypeParameters()));
        System.out.println(Arrays.toString(particle.getClass().getTypeParameters()));
    }
}

 以上代码的输出结果为:

Java泛型探索

从以上内容可以发现,在泛型代码的内部,无法获得任何有关泛型参数类型的信息。

由第一个例子可以看出在运行时他们是相同的类型。

第二个例子只是看到了占位符的标识符,没有任何有用的信息。

2.擦除的问题

泛型不能用于显式的引用运行时类型的操作之中,例如转型、instanceof以及new。

class Frop<T> {
}

class Cat {
}


public class ErasedType {
    public static void main(String[] args) {
        Frop<Cat> frop = new Frop<Cat>();
    }
}

 上述代码中,只是看起来拥有相关参数的类型信息,T被Cat所替换,但是实际上并非如此,它只是一个Object。

3.擦除的补偿

class Building {
}

class House extends Building {
}


public class ErasedType<T> {
    Class<T> kind;

    public ErasedType(Class<T> kind) {
        this.kind = kind;
    }

    public boolean f(Object obj){
        return kind.isInstance(obj);
    }

    public static void main(String[] args) {
        ErasedType<Building> ctt1=new ErasedType<Building>(Building.class);
        System.out.println(ctt1.f(new Building()));
        System.out.println(ctt1.f(new House()));
        ErasedType<House> ctt2=new ErasedType<House>(House.class);
        System.out.println(ctt2.f(new Building()));
        System.out.println(ctt2.f(new House()));
    }
}

有时可以通过引入类型标签对擦除进行补偿,这意味着,有时候需要显式地将类型的Class对象进行传递。以便可以在类型表达式中使用。

4.边界

因为擦除移除了类型信息,但是泛型重用了extends关键字为泛型参数类型上设置限制条件。