美文网首页Android开发Android技术知识Android开发
学会Java泛型系列(三):泛型原理-擦除

学会Java泛型系列(三):泛型原理-擦除

作者: 涅小黑 | 来源:发表于2020-03-24 08:19 被阅读0次

前面提到过,Java泛型是1.5才引进来的,不像其他语言天生就支持泛型。为了兼容1.5之前的代码,Java从编译器动手,使用擦除的手段支持泛型,这也使得Java的泛型有局限性。下面讲解擦除的原理及其局限性,对Java泛型有个全面的了解,在使用泛型的时候不再疑惑。

擦除

    List<String> strList = new ArrayList<>();
    List<Integer> intList = new ArrayList<>();

    System.out.println(strList.getClass().getName()); //java.util.ArrayList
    System.out.println(intList.getClass().getName()); //java.util.ArrayList
    System.out.println(strList.getClass() == intList.getClass()); //true

可见,在运行时List<String>与List<Integer>的类型信息是一样的

class Holder<T>{
    private T t;

    public Holder(T t){
        this.t = t;
    }

}


Holder<String> stringHolder = new Holder<>("str");
Holder<Integer> intHolder = new Holder<>(123);
System.out.println(Arrays.toString(stringHolder.getClass().getTypeParameters())); //[T]
System.out.println(Arrays.toString(intHolder.getClass().getTypeParameters())); //[T]

getTypeParameters返回泛型声明对应的类型参数,从打印上看到并不是返回具体的类型,二是返回[T],是一个占位标识符。
泛型会擦除掉类型参数,类里面的声明会变成类型边界(类型边界后面会讲到),如果没有声明类型边界就是Object。当你想使用T的时候,不知道它具体的类型,只能当做类型边界的类,调用它的方法。

擦除只是在使用T的时候,上面看到stringHolder.get()的时候编译器会自动帮我们把返回的参数转换为String类型

边界

class Animal{
    private String name;
    
    public Animal(String name){
        this.name = name;
    }

    public String getAnimalName() {
        return name;
    }
}

class Holder<T>{
    private T pet;
    
    public Holder(T t){
        pet = t;
    }
    
}


class Holder2<T extends Animal>{ //声明Animal为类型参数的边界
    private T pet;

    public Holder2(T t){
        pet = t;
        pet.getAnimalName(); //类型擦除到第一边界,可以有多个边界
    }

}

Holder2声明了类型参数的边界,编译器实际上会把类型参数替换为它的擦除,T就相当于Animal,pet就行可以使用Animal的方法,相应地pet也只能接收Animal或者Animal的子类

Holder2 holder2 = new Holder2<>(new Animal("aaa"));
Holder2 holder3 = new Holder2<>(new Dog("bbb"));
Holder2 holder4 = new Holder2<>(new Object()); //编译不通过

多边界

边界可以定义多个,与集成一样,只能定义一个class的边界+多个接口的边界,并且class必须放在开始

class Animal{
    private String name;

    public Animal(String name){
        this.name = name;
    }

    public String getAnimalName() {
        return name;
    }
}

interface Fly{
    void fly();
}

interface Run{
    void run();
}

class Holder<T extends Animal & Fly & Run>{
}

目录

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

相关文章

网友评论

    本文标题:学会Java泛型系列(三):泛型原理-擦除

    本文链接:https://www.haomeiwen.com/subject/xnopyhtx.html