初识泛型擦除

多次听到泛型擦除也看过不少的博客解释,但始终都是看的时候觉得挺有道理一转眼就忘的一干二净,归根结底是没有自己的认识。所以我今天翻看了ArrayList的实现源码来真真正的认识一下泛型擦除。
我们都用过ArraryList类,都知道他是一个容器类,并且从javase5之后是一个类型安全的容器类(我们再使用他的时候必须指定这个泛型的具体类型,然后在使用他的过程中也只能向这个容器中添加这个类型的对象,最后使用get方法获得的也一定是这个类型的对象),具体使用如下所示:

package test;

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        List<Apple> list = new ArrayList<Apple>(); //"<>"中指定泛型的具体类型为Apple
        list.add(new Apple());   //添加Apple类型的对象,成功
        //list.add(new Orrange());   //添加Orrange类型的对象,报错
    }
    static class Apple {

    }
    static class Orrange {

    }
}

按照这个思路思考的话,那ArrayList中保存的就应该是Apple类型的对象,而不是其他的类型,但事实上却不是这样。在ArrayList中Apple的对象却是以Object类型进行保存(进行了向上转型),并不是以我们指定的Apple类型进行保存。来看源码:

在这里插入图片描述
在这里插入图片描述
可以看到elementData数组的类型为Object类型,add方法直接将添加的对象添加到了elementData数组。这种对象保存到容器中失去了原来的类型统一转型为Object类型的现象就叫泛型擦除。

现在我们就有疑问了,既然统一擦除了原来的类型那又怎么保证get方法得到的对象不是Object类型而是对象的原来类型呢?接下来我们看get方法的源码:
在这里插入图片描述
可以看到在每次返回元素的时候都是用了"(E)"进行强转。这样我们get到的结果就是原来的类型了。

添加数据的时候上转为Object类型,查找数据的时候有强转为原来的类型,这样转过来转过去的有什么意义呢?为什么直接创建一个E类型的数组而多此一举的创建Object类型的数组呢?原因是泛型是不能创建数组的

public class Apple<E> {
        E []e = {};   //报错
        E []ee = new E[10];   //报错
    }
发布了57 篇原创文章 · 获赞 55 · 访问量 1956

猜你喜欢

转载自blog.csdn.net/qq_40561126/article/details/104255902