A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张东贤 中级黑马   /  2013-3-20 22:45  /  1527 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张东贤 于 2013-3-20 23:56 编辑

哪位大神能解释下,向上限定泛型啊

了解了解,谢谢了

2 个回复

倒序浏览
泛型的限定:用于泛型扩展用得。利用通配符?就可以实现泛型的限定:
? extends E:可以接收E类型或者E的子类型。这就是上限。
? super E:可以接收E类型或者E的父类型。这是下限。
回复 使用道具 举报
1,集合和泛型

在没有给集合制定类型时,一个集合可以加入任何类型的数据,但是规定了类型之后,则只能放同一种类型的数据

2,泛型是jdk1.5的新特性

3,去类型化(泛型基本可以说是通过编译器实现的,在运行阶段类型会被擦除)

ArrayList<String> lista = new ArrayList<String>();

ArrayList<Integer> listb = new ArrayList<Integer>();

if(lista.getClass() == listb.getClass()){

         System.out.println(true

);

运行的时候去类型化,编译完的字节码是同一个,里面已经没有泛型信息,

所以,泛型是给编译器看的,如果绕过编译器,直接操作字节码,泛型的作用就消失了,比如下面的例子

在一个ArrayList<Integer>里面不能直接添加一个String,因为这个时候编译器会报错,而如果用反射,则可以实现




[java] view plaincopyprint?
01.ArrayList<String> lista = new ArrayList<String>();  
02.lista.add("abc");  
03.//下面一句则会出错,被编译器检查出与泛型信息不匹配   
04.//lista.add(1);         
05.lista.getClass().getMethod("add", Object.class).invoke(lista, 1);  
06.System.out.println(lista);  
4,关于泛型的转化兼容关系
看下面代码,大致就能理解常见的转化关系




[java] view plaincopyprint?
01.             //原始类型可以 和实例化了的泛型类型相互赋值  
02.ArrayList<String> lista = new ArrayList();  
03.ArrayList listb = new ArrayList<String>();  
04.  
05.//参数类型不考虑参数的继承关系,无论是向下转型还是向上转型  
06.//ArrayList<String> listc = new ArrayList<Object>();  
07.//ArrayList<Object> listd = new ArrayList<String>();  
08.//但是,注意,这样则无错  
09.ArrayList liste = new ArrayList<String>();  
10.ArrayList<Object> listf = liste;  
11.  
12.//不能创建数组元素为参数类型的数组  
13.//ArrayList<String>[] array = new ArrayList<String>[10];  



5,问号通配符  ?

作用:问号通配符可以指向各种参数化的引用类型,通配符定义的变量,可以调用与参数化无关的方法(和泛型无关),但是不可以调用和参数化有关的方法

下面是一个输出任何类型集合类的一个方法




[java] view plaincopyprint?
01.public static void PrintAllCollection(Collection<?> collection){  
02.    //不可以调用和参数化有关的方法,但是可以调用和参数化无关的方法  
03.    //collection.add(1);   //error  
04.    collection.size();  
05.      
06.    for(Object obj:collection){  
07.        System.out.println(obj);  
08.    }  
09.      
10.    //下面一行也是正确的,相当于调用桉树时的转化  
11.    collection = new ArrayList<String>();  
12.}  




6,通配符的扩展

限定通配符的上边界

   Vector<? extends Number> vec = new Vector<Integer>();   //  right
    Vector<? extends String> ved = new Vector《Float>();         //  error

限定通配符的下边界
    Vector<? super Integer> vee = new Vector<Number>();   //  right
    Vector<? super String> vef = new Vector《Float>();         //   error


提示

限定通配符包括自己




关于向上向下转型请看这篇简明扼要的文章 java泛型中的上界下界(上限下限)




下面是关于上界下界的另一个例子

关于?extends




[java] view plaincopyprint?
01.              List<Apple> apples = new ArrayList<Apple>();  
02.List<? extends Fruit> fruits = apples;  
03.//error--fruits.add(new Strawberry());  
04.//error--fruits.add(new Apple());  
05.//error--fruits.add(new Fruit());  
06.Fruit get = fruits.get(0);  
07.//原因  
08./*
09. * 你可以这样想:这个? extends T 通配符告诉编译器我们在处理一个类型T的子类型,
10. * 但我们不知道这个子类型究竟是什么。因为没法确定,为了保证类型安全,
11. * 我们就不允许往里面加入任何这种类型的数据。另一方面,因为我们知道,不论它是什么类型,
12. * 它总是类型T的子类型,当我们在读取数据时,能确保得到的数据是一个T类型的实例:
13. */  

关于? super




[java] view plaincopyprint?
01.List<Fruit> fruits2 = new ArrayList<Fruit>();  
02.// error----List<? super Apple> = fruits2;  
03.//我们看到fruits指向的是一个装有Apple的某种超类(supertype)的List。  
04.//同样的,我们不知道究竟是什么超类,但我们知道Apple和任何Apple的子类都跟它的类型兼容。  
05.//既然这个未知的类型即是Apple,也是GreenApple的超类,我们就可以写入:  
06.  
07.fruits2.add(new Apple());  
08.fruits2.add(new GreenApple());  
09.//如果我们想往里面加入Apple的超类,编译器就会警告你:  
10.  
11.//error --- fruits2.add(new Fruit());  
12.//error --- fruits2.add(new Object());  
13.//因为我们不知道它是怎样的超类,所有这样的实例就不允许加入  
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马