集合使用有限限制条件的通配符之后的数据的读取和写入 [Java]

集合使用有限制条件的通配符之后的数据的读取和写入

读取:

? extends T ---- 类型上限

如果是? extends T的形式,这个时候我们读取的时候就可以通过T类型接收返回值,而不是通过使用Object类型,因为这个时候我们最多能配对的泛型的类型就是T类型,这个时候如果我们使用T类型的引用就足以接收

package 泛型.通配符;

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

public class Demo2 {
    public static void main(String[] args) {
        List<? extends Number> list1 = null;

        List<Integer> list2 = new ArrayList<>();
        list2.add(1);
        list2.add(2);
        list2.add(3);
        list2.add(4);

        list1 = list2;
        /* 
        这个时候我们就使用Number类型的引用就可以了,不用使用Object类型的引用,因为这个时候这个类型通配符中最多能匹配的就是
        Number类型的数据了,如果是Object类型,这个时候肯定就不能匹配,那么我们使用Number类型的引用这个时候就可以和集合中的返回值形成多态
        ,就已经足够了
         */
        Number number = list1.get(0);
        System.out.println(number);
    }
}

? super T — 类型下限

如果是? super T的形式,这个时候我们就还必须是Object类型的引用去接收我们使用这个泛型为? super T 类型的类创建出来的对象调用的get()方法的返回值,这个时候我们的这个通配符可以接收T类型的数据,也可以接收T类型的父类类型的数据,这个时候我们T类型的最终的父类也就是肯定是Object类型,所以我们就要使用Object 类型去接收这个返回值,才能和我们这方法的实际返回值形成多态

eg:

package 泛型.通配符;

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

public class Demo3 {
    public static void main(String[] args) {
        List<? super Number> list1 = null;

        List<Object> list2 = new ArrayList<>();
        list2.add(1);
        list2.add(2);
        list2.add(3);
        list2.add(4);

        
        list1 = list2;
        /*
        这个时候我们必须要使用Object类型的引用来接收这个返回值,因为这个时候我们的? super Number可以配Number 类型和Number的父类类型,这个时候
        我们的Number类型的父类类型就是Object类型,这个时候如果我们要接收这个get()方法的返回值,那么这个时候自然我们要使用Object类型的引用
        来接收这个方法的返回值
         */
        Object number = list1.get(0);
        System.out.println(number);
    }
}

写入:

? extends T ---- 类型上限

如果是? extends T 这个时候我们是不可以写入数据的,除了null

  • 因为 ? extends T是可以匹配T类型和T类型的子类类型,这个时候我们不知道这个类的具体泛型

    • 这个时候我们可以有数学归纳法得出结论:

      这个时候假设集合G< A>继承了集合G< B>这个时候对于G<? extends B>的集合来说,这个时候如果我们要在这个集合中写入数据,这个时候我们写入G< A>类型的数据,这个时候可以写入成功? —显然是不可能写入成功的,这个时候我们的G< A>肯定也有子类,比如说是G< C>继承了G< A>,这个时候如果我们的泛型通配符配的是G< C>,那么这个时候我们肯定就推翻了之前写入G< A>类型数据的想法,因为这个时候我们声明为G< C> ,这个时候只能填入G< C>类型的对象或者是G< C>类型的子类类型的对象,这个时候我们的G< C>又有子类,G< C>的子类还有子类 — 这个时候就无限循环了下去 -------- 这个时候最终就得出一个结果 : ? extends T的形式不可以写入数据 (除了null之外)

  • null可以写入,但是写入null其实就相当于没写,所以我们也就说? extends T的形式的通配符不可写入数据

eg:

package 泛型.通配符;

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

public class Demo4 {
    public static void main(String[] args) {
        List<? extends Number> list1 = null;

        List<Integer> list2 = new ArrayList<>();
        list2.add(1);
        list2.add(2);
        list2.add(3);
        list2.add(4);

        list1 = list2;
        /*
        这个时候我们就使用Number类型的引用就可以了,不用使用Object类型的引用,因为这个时候这个类型通配符中最多能匹配的就是
        Number类型的数据了,如果是Object类型,这个时候肯定就不能匹配,那么我们使用Number类型的引用这个时候就可以和集合中的返回值形成多态
        ,就已经足够了
         */
        
        list1.add(null);//这个时候编译是通过的因为我们? extends T的形式只可以添加null
        
        list1.add(1); //这个时候编译就会出错,? extends T只可以添加null,其余任何都不可以添加
    }
}

? super T ---- 类型下界

如果是? super T 形式的,这个时候我们就可以写入T类型的数据,或者是写入T类型的子类类型的数据,这个时候因为我们的? super T 的形式可以配对 T类型和T类型的父类类型,这个时候我们的这个通配符最小类型也要为T类型,这个时候如果我们在这个通配符为泛型的类中,那么肯定就可以以多态的形式添加T类型子类类型的数据,当然也可以添加T类型的数据,如果是添加的T类型的数据,这个时候有可能是以多态的形式添加,也有可能是以本类的引用指向本类的对象

eg:

package 泛型.通配符;

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

public class Demo5 {
    public static void main(String[] args) {
        List<? super Number> list1 = null;

        List<Object> list2 = new ArrayList<>();
        list2.add(1);
        list2.add(2);
        list2.add(3);
        list2.add(4);


        list1 = list2;
        /* 
        这个时候我们写入了一个Double类型的数据,这个时候我们写入的Double类型的数据就是以Number类型的子类类型的形式写入的,
        这个时候我们输入的Double类型的对象就也这个具体泛型类的引用以多态的方式进行连接
         */
        list1.add(1.0);  //这个时候编译是通过的,这个时候我们可以写入Number类型的数据,和Number类型的子类类型的数据
    }
}

读取:

如果是? extends T

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值