15.9泛型边界知识整理

看到泛型边界,这一章开始看得有点晕,所以看了下其他人的博客:

https://blog.csdn.net/jiuoop/article/details/24980991

https://blog.csdn.net/bbbbln/article/details/51943006

关于extends 和 super 写下自己的理解:

在这里首先要说:

泛型不具备协变性。

List<Object> list2 = new ArrayList<Integer>();

上面代码无法通过编译。


List<? extends Number> list1 = new ArrayList<>();

在这里 Number 被划分为上边界,这个集合想表达的意思是: 具有任何从Number继承类的类型的列表。

在这个集合中,?表示具体类型,因为只划分了上边界,所有没有最低保证,在添加的时候,无法判断这个容器到底是持有的哪个类型,只能保证它至少具有Number类型,这样在添加的时候,就有可能出现:

        List<? extends Number> list1 = new ArrayList<Integer>();
        list1.add(12.2);
add(? Extends Number e) 添加的时候不知道具体类型,没有办法保持数据的一致性,这里可能会有疑问,为什么不向上转型为Number? ,注意第一条协变性。

所以啊,add被禁止掉,而获取就不一样了,因为至少能够保证Number的方法,所以获取提供向上转型,这是安全的

所以add(? Extends Number e) 不接受任何类型的 Number,所以,不接受任何参数,null除外

查看相关源码:

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

这里是使用的泛型参数:并没有提供向上转型的Object,而是add(E e),这里说明,那些方法是需要安全的,取决于设计者自己,通过判断泛型参数(extends),能够知道这个方法是否能被调用




List<? super Number> list1 = new ArrayList<>();

在这里,Number被划分为下边界,这个集合想表达的意思是: 具有任何从Number父类的类型的列表。

在这个集合中,?依然代表具体类型,但是由于划分出了下边界,所以就有了底线,无论如何,都能保证在这个容器中的对象不会越过这条底线,所以,就有了一种安全的做法:

List<? super Number> list1 = new ArrayList<>();
        list1.add(12);
        list1.add(12.2);

这是可以编译通过的:因为持有的都是Number的父类,所以,在底线下面的对象通通都是安全的:比如

List<? super Number> list1 = new ArrayList<Object>();
        list1.add(12);
        list1.add(12.2);




猜你喜欢

转载自blog.csdn.net/perfect_red/article/details/80891940