• Java那些事-泛型通配符


    Java的类型通配符,可以出现在类、方法上面。最常用的方式就是集合类,例如List,Set等类上面。

    通配符类型

    • 有泛型参数 List
    • 有无类型标识 List< ? >
    • 有通用的标识 List< object >
    • 边界通配符 List<? extends Class>
    • 边界通配符 List<? super Class>

    本文主要讨论的是最后的关于边界的通配符类型。

    看一个例子

    public static void main(String[] args) {
            List<B> bList = new ArrayList();
            bList.add(new A());
            bList.add(new B());
            bList.add(new C());
            A a3 = bList.get(0);
            B b3 = bList.get(0);
            C C3 = bList.get(0);
    
            List<? extends B> bExtends = new ArrayList();
            bExtends.add(new A());
            bExtends.add(new B());
            bExtends.add(new C());
            A a1 = bExtends.get(0);
            B b1 = bExtends.get(0);
            C C1 = bExtends.get(0);
    
            List<? super B> bSuper = new ArrayList();
            bSuper.add(new A());
            bSuper.add(new B());
            bSuper.add(new C());
            A a2 = bSuper.get(0);
            B b2 = bSuper.get(0);
            C C2 = bSuper.get(0);
        }
    }
    class A {
        String a = "a";
    }
    class B extends A {
        String b = "b";
    }
    class C extends B {
        String c = "c";
    }
    

    有三个类,继承关系是A < B < C。
    然后声明了三个数组,list,extends,super.
    上面的代码是编译不通过的。分别在第3、7、11-13、16、19、22-24行。

    原理分析

    List<? extends B> 得到的是B及B的子类的一个集合。
    List<? super B> 得到的是B及B的父类的一个集合。
    List 得到的是一个B的集合。

    1. ? extends B 声明了上界标识符、不定下界,而add(E e)的时候,编译器无法确定e需要分配的声明类型,虽然有实际类型,这个地方跟多态不一致,所以编译器不通过;而get(int i)的操作,会获取到一个肯定是B的元素,故是安全的。
    2. ? super B正相反,声明的是下界标识符、不定上界(Object),当add(E e)的时候,添加的是子类型,子类型向上转型是安全的;get(int i)的时候,并不能确定拿到的会是一个怎样的类型,可能是Object,也能是A,故也是违规的。
    3. B 声明的是上下界为B。add(E e)按照多态性,可以添加为B的类型及其子类型;get(int i)返回的必然是B的类型。

    代码错误验证

    按照第1条解释,第3、11-13行的错误符合解释。
    按照第2条解释,第19、22-24行的错误符合解释。
    第7、16行是由于向下转型是不安全的,股编译错误。

    小结

    extends和super别定义了上下限,结论如下面的表格

    extends super T
    add unsafe safe safe
    get safe unsafe safe
  • 相关阅读:
    PHP 如何阻止用户上传成人照片或者裸照
    centos 从php5.1升级php到5.3的方法
    用jQuery实现鼠标移动切换图片动画
    利用表格实现大图轮播
    css导行下拉动画
    java script 基本函数
    java script 数组去重两种方法
    java script两个列表之间移动数据
    JavaScript做个时间表 Date()
    JS For 循环详解;棋盘放粮食 64;冒泡排序实例
  • 原文地址:https://www.cnblogs.com/jason0529/p/9150855.html
Copyright © 2020-2023  润新知