zoukankan      html  css  js  c++  java
  • 泛型通配符

    上一节讲到,泛型是不变的,可有时候需要实现协变,在两个类型之间建立某种类型的向上转型关系,应该使用通配符.

    概览

    泛型通配符有三种:

    • ? 任意类型,如果没有明确,那么就是Object以及任意的java类
    • ? extends E 向下限定,E及其子类
    • ? super E 向上限定,E及其父类

    ? 通配符

    首先定义两个类

    class Person{
        public void say(){
            System.out.println("person say hi!!");
        }
    }
    class Student extends Person{
        @Override
        public void say() {
            System.out.println("student say hi!!");
        }
    }
    
        @Test
        public void testArrayList(){
            ArrayList<?> list = new ArrayList<>();
            list.add("helo");
        }
    

    上面的代码,看上去就是对"?"通配符的使用,而且看起来并没有任何逻辑问题,定义一个任意类型的泛型,然后添加String类型的值,但是list.add("helo");会报错,list不能添加数据,因为"?"通配符不是这么使用的.

    泛型通配符不是用在定义对象上,而是用在方法形参上.

     @Test
        public void testArrayList(){
            ArrayList<Student> list = new ArrayList<>();
            list.add(new Student());
            method(list);  //可以传入Student的类型
    
            ArrayList<Person> list2 = new ArrayList<>();
            list2.add(new Person());
            method(list2);  //可以传入Person的类型
            
        }
    
        public static void method(ArrayList<?> list){    //定义泛型通配符 ,这个方法可以传入任意类型的泛型.
            for (Object o : list) {
                System.out.println(o);
            }
        }
    

    ? extends E

    ? extends E 是上界限定,限定了天花板,只能是E及其子类

        @Test
        public void testExtendArray(){
            ArrayList<Person> list1 = new ArrayList<>();
            list1.add(new Person());
            method2(list1);  //method2中传入Person类的实例,没有问题
            ArrayList<Student> list2 = new ArrayList<>();
            list2.add(new Student());
            method2(list2);  //method2中传入Student类的实例,也没有问题,因为Student继承Person
            ArrayList<Object> list3 = new ArrayList<>();
            list3.add("");
            method2(list3); //这里就会出错,因为Object不是Person的子类,所以不能这样使用. //error
        }
        public static void method2(ArrayList<? extends Person> list){  //这里就是接受Person及其person子类对象的list
            for (Person person : list) {
                System.out.println(person);
            }
        }
    

    ? super E

    ? super E 是下界限定,限定为E及其父类

    @Test
        public void testSuperArrayList(){
            ArrayList<Person> list = new ArrayList<>();
            list.add(new Person());
            method3(list);  //传入Person类型的ArrayList 没有问题
            ArrayList<Object> list2 = new ArrayList<>();
            list2.add("");
            method3(list2);  //传入Object类型也没有问题,因为Object是Person的父类
            ArrayList<Student> list3 = new ArrayList<>();
            list3.add(new Student());
            method3(list3); // error 在这里就会出错,是因为Student不是Person的父类
        }
        public static void method3(ArrayList<? super Person> list){  //这里限定为Person及其父类
            for (Object o : list) {
                System.out.println(o);
            }
        }
    
  • 相关阅读:
    关于WPF的控件对齐方式
    RTC与WebRTC有什么区别
    Ubuntu 14.04 单机安装 CEPH
    【DP专题】——棋盘分割
    征战蓝桥 —— 2015年第六届 —— C/C++A组第9题——垒骰子
    征战蓝桥 —— 2015年第六届 —— C/C++A组第9题——垒骰子
    征战蓝桥 —— 2015年第六届 —— C/C++A组第9题——垒骰子
    征战蓝桥 —— 2014年第五届 —— C/C++A组第10题——波动数列
    征战蓝桥 —— 2014年第五届 —— C/C++A组第10题——波动数列
    征战蓝桥 —— 2014年第五届 —— C/C++A组第10题——波动数列
  • 原文地址:https://www.cnblogs.com/liuzhidao/p/13745296.html
Copyright © 2011-2022 走看看