• java泛型上下限


    前言:

      java的泛型上下限不是很好理解,尤其像我这种菜鸡。反反复复看了好几遍了...,真是...

    一、简单的继承体系

    class Person{}
    
    class Student extends Person{}
    
    class Worker extends Person{}

    二、泛型上限(extends 关键字)

    public static void upperBound(List<? extends Person> list, Person p){
            //正确,因为null没有类型信息  
            list.add(null);
            //错误,因为list的参数类型可能是Person的子类
            list.add(p);①
            //成功获取
            if(list.size() > 0){
                Person pp = list.get(0);②
            }
        }

      ①处的错误在于list的参数类型是不确定的,其参数类型可能是 Person的子类,子类集合(List)不能添加父类的元素。测试如下:

    public static void testUpperBound(){
            ArrayList<Student> slist =  new ArrayList<Student>();
            Person p = new Person();
            upperBound(slist, p);//无法添加成功
        }

      如何解决泛型上限添加问题,可以使用泛型方法,如下:

    public static <T extends Person> void upperBound2(List<T> list, T p){
            list.add(p);
        }
    public static void testUpperBound2(){
            ArrayList<Person> plist =  new ArrayList<Person>();
            Person p = new Person();
            Student s = new Student();
            upperBound2(plist, p);
            
            upperBound2(plist, s);
        }

      也就是说,使用泛型上限add方法时,集合参数类型 和 元素参数类型 要一致,这样添加的时候才不会有矛盾。看一下eclipse中对upperBound2(plist, s);这个函数调用的提示,如下:

      可见,T类型最终会解析为 泛型的最上限类型,Student s相应的向上转型。

      接着说 ② 处,为什么能获取成功呢?泛型上限嘛,至少上限的类型是确定的,所有的上限类型的子类都可以进行向上转型,自然获取是不成问题了。

    三、泛型的下限

    public static void lowerBound(List<? super Student> list){
            Person var = new Person();
            //错误,list的参数类型可能是 Student,这样就不能添加父类Person了,所以 变量var的类型 必须是 Student或者 Student的子类
            list.add(p);①
            //正确
            Student s = new Student();
            list.add(s);
        }
    public static void testlowerBound(){
            ArrayList<Person> list = new ArrayList<Person>();
            lowerBound(list);
        }

      ①处添加失败,告诉我们,泛型下限使用add方法添加元素时,元素的参数类型必须是 下限 或者 下限的子类型。否则会出现子类集合添加父类元素。

    public static void lowerBound2(List<? super Person> list){
            Person p = new Person();
            list.add(p);
            //获取,不能编译
            Person as = list.get(0);①
        }
    public static void testlowerBound2(){
            ArrayList<Person> list = new ArrayList<Person>();
            lowerBound2(list);
        }

      ①处获取失败了,我们看一下eclipse提示我们该怎么办?

      将 第二个方法 将"as"的类型更改为"Object"  和 泛型的下限 结合一下考虑一下,add(e)方法在正确添加后,都会成为Object对象,在使用get(index)方法时,会转换为 

    ? super Person类型(可能是Person类型,也可能是Person的父类类型,甚至是Object),执行Person as = list.get(0),那么就有了 向下转型。java中无法保证向下转型是安全的。所以①处不能编译。

    四、泛型上限最常见的一个应用

    List<Person> plist = new ArrayList<Person>();
    List<Student> slist = new ArrayList<Student>();
            
    plist.addAll(slist);

    五、泛型下限最常见的一个应用

    Set<Student> set = new TreeSet<Student>(new Comparator<Person>() {
        @Override
        public int compare(Person o1, Person o2) {
            return 0;
        }
    });

    六、泛型上下限一个综合的例子

      注:个人瞎掰的...,就是将上面两个例子结合在一起!

    Set<Person> set = new TreeSet<Person>(new Comparator<Person>() {
        @Override
        public int compare(Person o1, Person o2) {
            return 0;
        }
    });
    List<Student> slist = new ArrayList<Student>();
    List<Worker> wlist = new ArrayList<Worker>();
    set.addAll(slist);
    set.addAll(wlist);

      接下来,研究一下泛型的擦除...

  • 相关阅读:
    CodeForces 19D Points (线段树+set)
    FZU 2105 Digits Count
    HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)
    HDU 5634 Rikka with Phi (线段树)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
  • 原文地址:https://www.cnblogs.com/hujunzheng/p/5351697.html
Copyright © 2020-2023  润新知