• 6、通配符的使用


    通配符的使用:

    类型通配符:? 
     比如:List<?>,Map<?,?> List<?> 是 List<String>、List<Object> 等各种泛型 List 的父类。
     读取 List<?> 的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。
     写入list中的元素时,不行。因为我们不知道真正的元素类型,我们不能向其中添加对象。唯一的例外是null,它是所有类型的成员。 
     
    通配符使用的注意点:
    1、不能用在泛型方法声明上,返回值类型前面<>中不能使用? 
    2、编译错误:不能用在泛型类的声明上 
    3、不能用在创建对象上,右边属于创建集合对象 
    
    有限制的通配符:
    1、<?>:
     允许所有泛型的引用调用 
    2、通配符指定上限 
     上限extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即<=;
     <? extends Number>,(无穷小 , Number]:只允许泛型为 Number 及 Number 子类的引用调用;
    3、通配符指定下限 
     下限super:使用时指定的类型不能小于操作的类,即>=;
     <? super Number>,[Number , 无穷大):只允许泛型为 Number 及 Number 父类的引用调用;
    
    
    
    实例1:
    public class GenericTest {
    
        @Test
        public void test3() {
            List<Object> list1 = null;
            List<String> list2 = null;
    
            List<?> list = null;
    		// 编译通过
            list = list1;
            list = list2;
        }
    }
    
    实例2:
    public class GenericTest {
    
        @Test
        public void test3() {
            List<?> list = null;
            // 编译报错,不能添加(写入)数据
            list.add("123");
            list.add(123);
            
            List<String> list2 = new ArrayList<>();
            list = list2;
            // 还是编译报错,不能添加(写入)数据
            list.add("123");
            list.add(123);
            
            // 这个是可以的
            list.add(null);
        }
        
        @Test
        public void test3() {
            List<?> list = null;
            
            List<String> list2 = new ArrayList<>();
            list2.add("AA");
            list2.add("BB");
            list2.add("CC");
            
            list = list2;
            
            // 获取(读取):允许读取数据,读取的数据类型为 Object。
            Object o = list.get(0);
        }
    }
    
    实例3:
    // 注意点1:编译错误:不能用在泛型方法声明上,返回值类型前面<>中不能使用? 
    public static <?> void test(ArrayList<?> list) {
        
    }
    
    //注意点2:编译错误:不能用在泛型类的声明上 
    class GenericTypeClass<?> {
    }
    
    // 注意点3:编译错误:不能用在创建对象上,右边属于创建集合对象 
    ArrayList<?> list2 = new ArrayList<?>();
    
    实例4:
    public class Person {
    
    }
    
    public class Student extends Person {
        
    }
    
    public class GenericTest {
    
        @Test
        public void test4(){
    
            List<? extends Person> list1 = null;
            List<? super Person> list2 = null;
    
            List<Student> list3 = new ArrayList<Student>();
            List<Person> list4 = new ArrayList<Person>();
            List<Object> list5 = new ArrayList<Object>();
    
            // 下面两个编译通过
            list1 = list3;
            list1 = list4;
            // 编译不通过
            // list1 = list5;
    
            // 编译不通过
            // list2 = list3;
            // 下面两个编译通过
            list2 = list4;
            list2 = list5;
        }
        
        @Test
        public void test4(){
    
            List<? extends Person> list1 = null;
            List<? super Person> list2 = null;
    
            List<Student> list3 = new ArrayList<Student>();
            List<Person> list4 = new ArrayList<Person>();
            List<Object> list5 = new ArrayList<Object>();
    
            // 读取数据:
            list1 = list3;
            Object o = list1.get(0);
            Person p = list1.get(0);
            // 下面这行不可以
            // Student s = list1.get(0);
            
            list1 = list4;
            Person p = list1.get(0);
            Object o = list1.get(0);
            // 下面这行不可以
            // Student s = list1.get(0);
            
            // 总结:最小要使用 Person 接收
            
            System.out.println("======================================");
    
            list2 = list4;
            Object o = list2.get(0);
            // 下面两行编译不通过
            // Person p = list2.get(0);
            // Student s = list2.get(0);
            
            // 总结:最小要使用 Person 的父类来接收  
            
            System.out.println("======================================");
    
            //写入数据:
            //编译不通过
    //        list1.add(new Student());
    
            //编译通过
            list2.add(new Person());
            list2.add(new Student());
    
        }
        
        @Test
        public void test4(){
    
            List<? extends Person> list1 = null;
            List<? super Person> list2 = null;
    
            List<Student> list3 = new ArrayList<Student>();
            List<Person> list4 = new ArrayList<Person>();
            List<Object> list5 = new ArrayList<Object>();
    
            // 写入数据:
            // 编译不通过
            // list1.add(new Student());
            // list1.add(new Person());
    
            // 编译通过
            list2.add(new Person());
            list2.add(new Student());
    
        }
    }
    
  • 相关阅读:
    linux环境变量(一)
    linux常用命令-ps
    linux实用小命令--查看文本内容
    postman tests常用方法
    Vue 中嵌套 Iframe,用postMessage通信 踩坑记
    [Vue warn]: Error in nextTick: "RangeError: Maximum call stack size exceeded"
    对STM32所用位带操作宏的详细剖析
    移植Modbus TCP二
    移植Modbus TCP一
    STM32位带操作
  • 原文地址:https://www.cnblogs.com/kehuaihan/p/13592448.html
Copyright © 2020-2023  润新知