zoukankan      html  css  js  c++  java
  • [转载]java泛型中的上界下界(上限下限)

    java泛型中的super关键字不太常用,也不太好理解,今天又从头看了看java的泛型机制,作一记录。 
    上界: 
    上界用extends关键字声明,表示参数化的类型可能是所指定的类型,或者是此类型的子类。如下面的代码: 

    Java代码  收藏代码
    1. public void upperBound(List<? extends Date> list, Date date)  
    2. {  
    3.     Date now = list.get(0);  
    4.     System.out.println("now==>" + now);  
    5.     //list.add(date); //这句话无法编译  
    6.     list.add(null);//这句可以编译,因为null没有类型信息  
    7. }  


    为什么会无法编译呢,实际调用时传入的list可能是java.util.Date的某个子类的参数化类型,如: 

    Java代码  收藏代码
    1. public void testUpperBound()  
    2. {  
    3.     List<Timestamp> list = new ArrayList<Timestamp>();  
    4.     Date date = new Date();  
    5.     upperBound(list,date);  
    6. }  


    也就是说,现在upperBound方法中实际的list是List<Timestamp>,向它添加一个Date类型,肯定是不行 的。相反,读取数据时,不管实际的list是什么类型,但可以知道它至少会返回一个Date类型,所以用foreach,get等没有问题。 

    那么如何解决呢,可以使用泛型方法 

    Java代码  收藏代码
    1. public <T extends Date> void upperBound2(List<T> list, T date)  
    2. {  
    3.     list.add(date);  
    4. }  


    这里方法声明中的T作为一种参数化信息,会存储在java字节码中,T的实际类型由调用时的参数决定的。比如: 

    Java代码  收藏代码
    1. public void testUpperBound2()  
    2. {  
    3.     List<Timestamp> list = new ArrayList<Timestamp>();  
    4.     Date date = new Date();  
    5.     Timestamp time = new Timestamp(date.getTime());  
    6.     upperBound2(list,time);  
    7.     //upperBound2(list,date);//这句同样无法编译  
    8. }  


    上面代码中的list的类型参数决定了方法中T的类型,所以会看到注释掉的内容不能编译。而换成这样: 
    List<Date> list2 = new ArrayList<Date>(); 
    upperBound2(list2,date); 
    编译就没有任何问题了。 


    下界 
    下界用super进行声明,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至Object。如下面的代码: 

    Java代码  收藏代码
    1. public void lowerBound(List<? super Timestamp> list)  
    2. {  
    3.     Timestamp now = new Timestamp(System.currentTimeMillis());  
    4.     list.add(now);  
    5.     //Timestamp time = list.get(0); //不能编译  
    6. }  


    这又为什么不能通过编译呢,看看调用代码: 

    Java代码  收藏代码
    1. public void testLowerBound()  
    2. {  
    3.     List<Date> list = new ArrayList<Date>();  
    4.     list.add(new Date());  
    5.     lowerBound(list);  
    6. }  


    lowerBound方法中的List<? super Timestamp>表示这个list的参数类型可能是Timestamp或Timestamp的父类,如后面测试代码里,实际传入的是一个 List<Date>类型。向List<Date>中add一个Timestamp肯定是没有问题的,但list.get()方 法返回的对象类型可能是Date甚至是Object,你不能说list.get(0)返回的就是一个Timestamp,这里是向下类型转换了,编译器无 法处理,所以这里不能编译。用java泛型实现的擦拭法解释,编译后会是如下的伪代码: 

    Java代码  收藏代码
    1. public void lowerBound(List list)  
    2. {  
    3.     Timestamp now = new Timestamp(System.currentTimeMillis());  
    4.     list.add(now);  
    5.     Timestamp time = (Timestamp)list.get(0); //①  
    6. }  
    7. public void testLowerBound()  
    8. {  
    9.     List list = new ArrayList();  
    10.     list.add(new Date());  
    11.     lowerBound(list);  
    12. }  


    代码①进行了强制类型转换,但实际添加进去的是一个Date类型,肯定会报ClassCastException,编译器无法保证向下类型转换的安全,所以这一句自然就无法编译了。

  • 相关阅读:
    WPF 关于拖拽打开文件的注意事项
    asp.net core 3.1中对Mongodb BsonDocument的序列化和反序列化支持
    用百度webuploader分片上传大文件
    多线程学习笔记
    web.config数据库连接字符串加密
    Visual Studio 2010 常用快捷方式
    Team Foundation Server 2013 日常使用使用手册(四)分支与合并
    Team Foundation Server 2013 日常使用使用手册(三)上传新工程、创建任务、创建bug、设置预警
    Team Foundation Server 2013 日常使用使用手册(二)修改、签入、撤销、回滚、对比代码变更
    Team Foundation Server 2013 日常使用使用手册(一)-本地连接TFS、查看任务
  • 原文地址:https://www.cnblogs.com/chenchong/p/2621076.html
Copyright © 2011-2022 走看看