学会Java泛型系列(四):擦除带来的问题以及解决办法

擦除带来的问题

擦除主要的正当理由是从非泛化代码到泛化代码的转变过程,以及在不破坏现有类库的情况下,将泛型融入Java中。

1.泛型不能用于显式地引用运行时类型的操作之中,例如instanceof、new

class Erased{

    public void f(T t,String a){
        //T t = new T(); //error
        //T[] ts = new T[100]; //error
        //boolean k = a instanceof T; //error
    }
}

我们可以把具体类型的Class传进来解决部分问题

class Erased{

    Class kind;
    
    public Erased(Class kind){
        this.kind = kind;
    }
    
    public void f(String a) throws Exception{
        T t = kind.newInstance(); //这个类需要有默认构造器,反射知识
        T[] ts = (T[]) Array.newInstance(kind,10);
        boolean k = kind.isInstance(a);
    }
}

2.基本类型不能作为参数类型

由于擦除的原因,类型参数会被擦除到上一边界,边界是一个类,不兼容基本类型,所以不能声明List

Java1.5后有自动包装机制,可以用List实现基本类型的泛化。但是要注意int[]与Integer[]是转化的,在一些需要传Integer[]的地方不能传int[].

3.数组

可以声明带泛型的数组引用,但是不能直接创建带泛型的数组对象

    List[] stringLists; //可以声明带泛型的数组引用
    List[] stringLists2 = new ArrayList[1];//不能直接创建带泛型的数组对象
    List[] stringLists3 = new ArrayList[1];

可以通过Array.newInstance(Class,int)来创建T[]

4.重载

class Holder{
    void f(List list){}
    void f(List list){}
}

上面的代码将会编译不通过,由于擦除的原因,这两个方法的类型签名是一样的。

5.基类劫持了接口

interface Run{
    void with(T t);
}

class Animal implements Run{

    @Override
    public void with(Integer integer) {}
}

public class Dog extends Animal implements Run{}//报错

子类与父类继承用一个泛型接口,如果两个泛型类型不同,将会被父类类型劫持

目录

学会Java泛型系列(零):简介及目录
学会Java泛型系列(一):Java泛型
学会Java泛型系列(二):泛型定义与使用
学会Java泛型系列(三):泛型原理-擦除
学会Java泛型系列(四):擦除带来的问题以及解决办法
学会Java泛型系列(五):限定符
学会Java泛型系列(六):总结
学会Java泛型系列(七):常用案例

你可能感兴趣的:(学会Java泛型系列(四):擦除带来的问题以及解决办法)