java吧 关注:1,272,316贴子:12,780,656
  • 32回复贴,共1
现在看JAVA泛型还是有点云里雾里,结论说list泛型上边界只能获取不能新增,下边界只能新增子类不能接收。不想只是背结论,看网上一些说法说第一种不确定类型所以不能新增,但是第二种就能确定类型吗,第三种也不算确认类型啊,为什么能新增呢


IP属地:湖南来自Android客户端1楼2022-10-21 12:25回复
    第三个确定了泛型类型是Object,所以可以用,上下界的限制只针对于不定类型的情况,即有个问号


    IP属地:四川来自Android客户端2楼2022-10-21 13:10
    回复
      2025-08-03 10:57:59
      广告
      不感兴趣
      开通SVIP免广告
      简单点说,?extends Father这个固定了上边界这个?可能是Father的任意子类,你在添加的时候你怎么保证你添加的子类元素都是?这一类型的元素所以不让你在固定上边界集合里添加元素
      ?super Father这个固定了下边界,添加的时候只能添加Father类和其子类,获取是可以获取的,但是由于没有上边界不知道这个?到底是Father的哪一个父类所以只能用顶级父类Object类获取
      第三种Object已经确定了最终类型就是Object所以你可以添加Object类和其子类
      我建议你看一下java的类型擦除和泛型编译,了解下后应该会理解这些


      IP属地:陕西来自Android客户端3楼2022-10-21 14:05
      收起回复
        首先,? xxx T,他是限定的泛型参数,你把这个List限定成某种类型才能使用,假如List中有多种类型,编译桥接时候可能发生强制转换错误,而且编译时候我不知道到底什么类型(编译时候会擦除类型)。
        ? extends T.为什么不行?
        假如限定List<? extends T>是T的子类,编译时候你给我放个father子类元素,我怎么你这个和son什么关系?所以防止发生桥接错误,干脆不让你放得了。
        ? super T为什么可以放?假如我限定List为son,我放个son进去没问题吧?放个dog没问题吧?为啥能放dog和son又不是同一个类型,不是同一个类型我能强制转换就行了,不会出问题。


        IP属地:广东来自Android客户端4楼2022-10-21 14:49
        收起回复
          把多态理解到位就全通了


          IP属地:上海来自Android客户端5楼2022-10-21 15:06
          回复
            还有你设计的这里继承链不合理,继承关系满足is a逻辑,Son is a Father, Dog is a Son,这个逻辑有点古怪和牵强,建议新手学多态选择明确的事物关系,比如“动物-人-具体的人”


            IP属地:上海来自Android客户端6楼2022-10-21 15:21
            收起回复
              你这个涉及到协变和逆变,多看下剥壳,PECS原则


              IP属地:广东来自Android客户端7楼2022-10-21 15:26
              回复
                协变逆变、JVM泛型源码、字节码反编译
                这三个相关的理解一下
                你就可以自豪的说你搞懂了Java泛型


                IP属地:上海来自Android客户端9楼2022-10-22 08:06
                收起回复
                  2025-08-03 10:51:59
                  广告
                  不感兴趣
                  开通SVIP免广告
                  <? extends T>与<? super T>
                  List 最大的问题是只能放置一种类型,如果随意转变类型的话,就是破窗理论,泛型就失去了意义。为了放置多种受泛型约束的类型,出现了 <? extends T>与<? super T> 两种语法。简单来说, <? extends T> 是Get First,适用于,消费集合元素的场景;<? super T>是Put First,适用于,生产集合元素为主的场景。
                  <? extends T> :可以赋值给任意T及T的子类集合,上界为T,取出来的类型带有泛型限制,向上强制转型为T。null 可以表示任何类型,所以null除外,任何元素都不得添加进<? extends T>集合内。
                  <? super T> : 可以复制T及任何T的父类集合,下界为T。再生活中,投票选举类似于<? super T>的操作。选举投票时,你只能往里投票,取数据时,根本不知道时是谁的票,相当于泛型丢失。
                  <? extends T>的场景是put功能受限,而<? super T>的场景是get功能受限。


                  IP属地:辽宁10楼2022-10-22 08:24
                  回复
                    你应该试下看new ArrayList<啥>()可以赋值给前面的泛型


                    IP属地:广东来自Android客户端11楼2022-10-22 13:09
                    收起回复
                      public static void main(String[] args) {
                      A a = new A();
                      B b = new B();
                      C c = new C();
                      D d = new D();
                      List<A> as = new ArrayList<>();
                      as.add(a);
                      as.add(b);
                      as.add(c);
                      List<B> bs = new ArrayList<>();
                      bs.add(b);
                      bs.add(c);
                      // error
                      // bs.add(a);
                      List<C> cs = new ArrayList<>();
                      cs.add(c);
                      // error
                      // cs.add(a);
                      // cs.add(b);
                      List<D> ds = new ArrayList<>();
                      ds.add(d);
                      List<? extends A> test1 = as;
                      List<? extends A> test2 = bs;
                      List<? extends A> test3= cs;
                      List<? extends A> testd= ds;
                      // 可以放任意子类的实现,对象可以直接调用他的任意方法
                      test1.get(0).testA();
                      // 这里的实际类型可能是 as bc cs ds, 所以其实往里面添加其实都是不安全的(我按照赋值进行了向下转换转换都存在无法设置的情况)
                      // ((List<D>)testd).add(a);
                      // ((List<B>)test2).add(d);
                      // ((List<C>)test3).add(b);
                      // ((List<D>)testd).add(c);
                      List<? super B> test4 = as;
                      List<? super B> test5 = bs;
                      // error
                      // List<? super B> test6 = cs;
                      // 因为可以赋值的是任意其父类,所以只有调用Object的方法都是安全的
                      test4.get(0).hashCode();
                      // 设的是他的子类是,他必然也是? super B的子类,所以也是绝对安全的
                      ((List<B>)test5).add(c);
                      }
                      static class A{
                      void testA(){}
                      }
                      static class B extends A{
                      void testB(){}
                      }
                      static class D extends A{
                      void testD(){}
                      }
                      static class C extends B{
                      void testC(){}
                      }


                      IP属地:广东12楼2022-10-22 15:04
                      回复
                        哦哦哦


                        来自iPhone客户端13楼2022-10-22 16:43
                        回复