黑马程序员——泛型

来源:互联网 发布:网页美工是做什么的 编辑:程序博客网 时间:2024/06/05 10:41

---------------------- ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ----------------------

泛型


泛型是JDK1.5加入的新特性,它以参数化类型的形式在编译期“过滤”不符合实际类型参数的数据,检查类型安全,减少安全隐患。类型参数可以加在类,接口和方法上。


泛型的生命周期


因为泛型信息信息基本都是在编辑期实现的,生成字节码后泛型信息就会被擦除,所以在运行期可以通过反射绕过编译期的泛型信息来操作参数类型的对象,这点张老师在视频上有讲过。

List list =new ArrayList<Integer>();//此时如果在list中加入的不是Integer类型编译器就报错//但我们通过反射可以绕过泛型并添加元素list.getClass.getMethod("add",Object.class).invoke(list,"hello,Cukoo");

而且,泛型参数的实际类型不能是基本数据类型,只能是引用数据类型,还有就是数组内的元素类型也不能是参数化类型,例如  List<String> [ ] arr=new ArrayList <String>[ ];


自定义泛型


class Operator<O>{void add(O obj){}O remove(O obj){}//上面是定义在类级别的泛型,类中的O类型参数被实际类型参数化后只要引用了这个O//都会是同一个类型,但是如果定义成: <O>O remove(O obj)的话就是独立的泛型方法了//而且静态方法不能引用类上定义的泛型的参数类型,除非自己定义成单独的泛型方法public static void add_2(O obj){} //这会发生异常public static <O>void add_2(O obj){} //正确//O在这里只是一个变量,只是它的实际参数是引用数据类型,换成T或者其他都一样}


通配符和范围限定


泛型中用?这个通配符表示任意类型,主要用来做引用,定义的方法中如果使用了<?>就只能调用与参数化无关的方法,不能调用与参数化有关的方法,例如定义方法: List<?>  list=new ArrayList()调用时候就不能使用list.add()这种跟参数类型有关的方法。

张老师在视频内有讲到一个问题,就是有的对象方法会返回一个”类名<?>“的对象,这时候你要么用一个非泛型类型的变量去引用,要么用带泛型的变量去引用,但是这个泛型变量的参数只能是<?>

如: Class类中的asSubclass()



将泛型类型的实际类型限定在某个接口或者父类及其子类范围之内:

ArrayList<? extends Number> list = new ArrayList<Integer>();

将泛型类型的实际类型限定在类及其父类的范围之内:

ArrayList<? super Integer> list = new ArrayList<Number>();


关于类型参数的类型推断

根据调用泛型方法时实际传递的参数类型或返回值的类型来推断,具体规则如下:

1.当某个类型变量只在整个参数列表中的所有参数和返回值中的一处被应用了,那么根据调用方法时该处的实际应用类型来确定,这很容易凭着感觉推断出来,即直接根据调用方法时传递的参数类型或返回值来决定泛型参数的类型

2.当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型都对应同一种类型来确定,这很容易凭着感觉推断出来

3.当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,且没有使用返回值,这时候取多个参数中的最大交集类型,

4.当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型, 并且使用返回值,这时候优先考虑返回值的类型

5.参数类型的类型推断具有传递性,下面第一种情况推断实际参数类型为Object,编译没有问题,而第二种情况则根据参数化的Vector类实例将类型变量直接确定为String类型

---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net
原创粉丝点击