黑马程序员技术交流社区
标题:
Java中的泛型
[打印本页]
作者:
Zhen_霖
时间:
2013-1-10 14:14
标题:
Java中的泛型
新人,刚刚加入论坛的!最近在看黑马程序员中Java EE的视频教程,感觉讲得真的太详细,太好了!下面有一些笔记想和大家分享一下,笔记如果有以下总结得不对的,希望大家指出来,谢谢!
Java中的泛型jdk1.5之后的一个重要的特性。
泛型:英文Generic
1.定义:泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。泛型类是引用类型,是堆对象,主要是引入了类型参数这个概念
2.使用jak中的泛型
(1) 声明一个ArrayList的容器对象可以使用泛型,用法是在类名后面加一对尖括号来指定具体的类型化参数
ArrayList<String> arrl= new ArrayList<String>();
//这样就指明了在这个ArrayList的容器中只能装类型类型为String的对象
arrl.add("sjkfh");
arrl.add(9);//这里编译器就会报错,因为声明的参数化类型是String类型的对象,不能add整数类型的对象
(2)泛型中的?通配符。使用?通配符就表明了这个泛型可以接受任何类型的参数,例如写一个方法它可以接受任何类型的参数,可以这样定义:
//体验泛型的?通配符,在泛型的尖括号中用问号来指定就不确定具体的类型是什么了,就可以统配任何类型了
//使用?通配符可以使用其他任何参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不可以调用与参数化有关的方法
public static void printColletion(Collection<?> collection){
System. out.println(collection.size());
for(Object obj:collection){
System. out.print(obj);
}
}
(3)?通配符的扩展:
[ ]限定通配符的上边界,如:
Vector<? extends Number> v1= new Vector<Number>();
这里是声明了Vector的对象的泛型,它参数化类型是任意的,但限定了范围,这里表明了它的参数化类型只能是Number以及继承了Number的之类的类型
[ ]限定通配符的下边界,如:
Vector<? super Integer> v2= new Vector<Number>();
同样的这里也定义了泛型的参数化类型,它的范围只能是Integer以及它的父类
3.自定义泛型。
(1)定义泛型的方法,要定义一个方法使它能作用于任何类型的参数可以这样写,在方法的返回值前面加上尖括号<E>如有返回值则应在泛型的后面指定同样的类型E
//定义一个方法 对传入的Object类型的对象转换成其他类型的对象
private static <T> T autoConvert(Object obj){
return (T)obj;
}
//定义一个方法,能打印出任意类型集合中的所有元素
public static <T> void printColletion1(Collection<T> collection){
System. out.println(collection.size());
for(Object obj:collection){
System. out.print(obj);
}
}
(2)定义泛型类,定义泛型类只需要在类名的后面加上尖括号<E>可以了
public class GenicDao<E>
需要注意的是:在类中定义的方法的类型必须严格按照类的泛型来定义,同时还不能有static方法,因为在泛型类中因为在泛型中只能指定了对象,而静态的方法直接用类名来调用则会混淆。如果你硬要定义静态方法则要在你定义的泛型方法中自定义泛型
public static <E> void updeta2(E e){
}
注意这里的E和类中的E是两个不同的概念哈!
4.在java中的泛型它只是给编译器看,在编译器编译变成字节码后,它的具体的参数化类型就没有区别了可以做这样的一个测试
ArrayList<String> arrl= new ArrayList<String>();
ArrayList<Integer> arr2= new ArrayList<Integer>();
System.out.println(arrl.getClass() == arr2.getClass());//output:true
[ ]从输出的结果为true可以看到这两份字节码是一样的,所以证明了泛型只是给编译器看,而编译过后则丢失了指定引用类型的区分。
[ ]另外一个泛型中的重要知识点:我们可以通过反射来透过编译器来获取泛型中的实际参数类型。首先说明一下,我们想通过获得类的字节码来区分一个集合里到底装的是什么类型,这样是行不通的,因为在编译器编译过后出来的字节码已经去掉了实际的参数类型。
另外一种做法是写一个方法
//定义一个方法对泛型中具体的参数类型进行操作
public static void applyGenic(Vector<Date> v1){
}
定义这个方法之后,我没有办法通过v1来获得前面这个变量的类型,但是我们可以通过这个方法来知道他的参数列表的类型
Method applyMethod=GenicTest.class.getMethod( "applyGenic" , Vector.class );
Type[] types=applyMethod.getGenericParameterTypes();
ParameterizedType pType=(ParameterizedType)types[0];
System. out.println(pType.getRawType());
System. out.println(pType.getActualTypeArguments()[0]);
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2