List<? extends Number> 和 List<? super Number> 对add函数区别

来源:互联网 发布:手机蓝牙连接器软件 编辑:程序博客网 时间:2024/05/18 20:12
这几天在 查阅泛型类型的使用和区别,遇到一个问题,,,挥之不去,萦绕在心头,久久不能释怀。。。问题如下:


问题一:


List<? extends Number>  list = new ArrayList<>();
list .add(100);  //这样的代码会报错的

     为啥这样的List就不能调用add函数呢?    奇怪,明明100是Integer对象类型,然后Integer是Number的子类,符合<? extends Number>上线限制的原则啊,,,为啥就报错了呢?

这样的问题,网上很多回答的,但总是说类型不安全,导致不让add。。。。说的一塌糊涂,,,让我想了好久,最后我根据我的理解,整理出来,方便大家理解,有哪里说的不对的,欢迎指正。


  答:1 .  List<? extends Number>  list  就是对加入的元素进行上限限制,,,只要是Number或者Number的子类都事可以的,,,但具体是哪一个?  大哥, 这谁知道啊,,,当然编译器也是不知道的,。。。。那编译器都不知道是什么类型,你就直接add一个Integer类型的,,,要是人家后面确定是Float类型的,那不就是搞错了吗?  这样的原因,导致java编译器直接就不让add了,从而避免了该问题的发生。
          2. 还有种解释是,,,现在JAVA的强类型检测,当编辑器遇到<? extends Number>时候,他只知道有东西要加入了,至于具体是什么类型,就不得而知了,所以在声明该变量的时候,只是存了一个变量加入类型的标记符,也就是占位符,具体是什么类型,还不能确定。。。当list调用add函数加入的时候, 会进行类型判断的,这个时候,因为上面保存的只是占位符,却没有真正的标记变量的类型。。。导致没法判断,就这样JAVAl数据类型的强类型问题问题,就会导致报错和各种问题,所以JAVA就直接不让add了,从而避免了该问题的发生。



问题二:



List<? super Number> listb = new ArrayList<>();
Integer a = 10;
listb.add(a);

listb.add((Object)a)    //这个的add会报错的


为啥这里的listb.add(a)不会报错,而listb.add(Object)对象会报错呢?


答:首先先说明下这里色List<? super Number> list,,,这个就是泛型的下线限制符。。。里面可以存储的对象是Number类以及Number类的父类。。。至于具体是哪个类型,就不得而知了。这就更奇怪了,为啥Integer类存储成功了,而Object类存储报错了。。。这是为啥呢?
        首先先说,为啥add Integer对象成功了。。。其实是这样的,因为JAVA的继承原理,对应的属性图都是从上到下的方式,Integer对象肯定是Number对象。。。而List<? super Number> list可以存储的就是Number类或者Number类的父类,但具体是哪个类型,就不得而知了。。。当然编译器也是不知道的。。。但就是因为JAVA的继承原理,让每一个Number子类都同时是Number类,,,同时也是所以Number父类的子类。。。这不就是完全符合了List<? super Number>list 可以存储的要求了吗?  因为Number子类,全部可以看成是Number类,然后Number类都是可以符合该List要求的。。。。那这样明显就可以存储成功了啊。。。
        然后在说add Object失败的问题,很明显,在申明一次,List<? super Number> list存储的只能是Number类或者Number类的父类,但具体是哪个类???  谁知道啊,,,有谁知道吗??? 鬼都不知道,编辑器当然也是不知道的

。。。这个时候,你add object对象,编辑器都不知道里面存储的数据类型,因为JAVA的强类型和Java类型检测机制,,,这里就会报错啦。。。。


问题3:


    基于上面的考虑,List<? extends Number>list 都不能add,,,那有这个东西有什么用呢?   这个自己体会吧,,,简单说明一下,抽象类和接口都不能new对象,怎么就那么大作用呢? 道理是一样的,,,比如如下: 

   List<? super Number>  list = new Arrary<>();

   List<Integer>  listb  = new Arrary<>();

   list  = listb;

    这就是用到的地方,对类型进行限制。。。其他的自己体会下吧,,,

    

总结:

     当考虑到要add时候,对于安全性的考虑,应该使用泛型的<? super XXX>模式,当考虑到要对list进行get类型显示的时候,就要考虑用到<? extends XXX>,这样的泛型才能起到,类型安全,并且简洁,程序员开发直观的效果!!!!!!









阅读全文
0 0
原创粉丝点击