java泛型上下限

简介:

v前言:

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

v一、简单的继承体系

class Person{}

class Student extends Person{}

class Worker extends Person{}

v二、泛型上限(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相应的向上转型。

 

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

 

v三、泛型的下限

复制代码
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中无法保证向下转型是安全的。所以①处不能编译。

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

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

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

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

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

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

复制代码
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);
复制代码

 

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

目录
相关文章
|
监控 Dubbo 搜索推荐
No application config found or it‘s not a valid config! Please add <dubbo:application name=“...“ />
No application config found or it‘s not a valid config! Please add <dubbo:application name=“...“ />
1632 1
|
7月前
|
Python
使用 Python 合并微信与支付宝账单,生成财务报告
这篇博客介绍了如何使用 Python 脚本合并微信与支付宝账单数据,生成自动化财务报告。通过 pandas 库,学习如何清洗、合并和分析账单数据,以及如何生成 Markdown 格式的财务报告。
|
NoSQL Java Redis
Redis 从入门到精通之Redis Pipeline
使用Redis Pipeline可以大大提高Redis的性能和吞吐量,但需要注意命令的顺序和语义,以保证数据的正确性和一致性。同时,使用Jedis和RedisTemplate实现Redis Pipeline时,需要遵循最佳实践,避免出现错误和异常。 2. 在使用Jedis实现Redis Pipeline时,需要使用Pipeline对象添加多个命令并执行,然后通过`syncAndReturnAll`方法获取所有命令的执行结果。 3. 在使用RedisTemplate实现Redis Pipeline时,需要使用`executePipelined`方法添加多个命令并执行,然后通过返回的结果列表获取
970 110
Redis 从入门到精通之Redis Pipeline
|
存储 监控 安全
JVM工作原理与实战(五):类的生命周期-加载阶段
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了类的生命周期、类的加载阶段等内容。
161 5
修改IDEA占用的内存大小
修改IDEA占用的内存大小
1263 0
|
编解码 Java 流计算
38款 流媒体服务器开源软件
http://www.oschina.net/project/tag/111/streaming?lang=0&os=0&sort=view&p=1 Flash流媒体服务器 Red5 Red5是一个采用Java开发开源的Flash流媒体服务器。
8695 0
|
XML JSON 缓存
【基于HTTP的远程调用框架 一】深度详解Retrofit2框架概念和使用
【基于HTTP的远程调用框架 一】深度详解Retrofit2框架概念和使用
957 0
|
NoSQL 算法 Java
Redis】redis连接池
Redis】redis连接池
484 0
|
JSON JavaScript 前端开发
接口测试之:Postman工具进阶教程。(二)
接口测试之:Postman工具进阶教程。(二)
435 0
接口测试之:Postman工具进阶教程。(二)
excel导入poi中的数据使用cell.getStringCellValue()获取报错
excel导入poi中的数据使用cell.getStringCellValue()获取报错
791 0