---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ---------------------
什么是泛型:
泛型是提供给javac编译器使用的,可以限定集合的输入类型,让编译器阻止源程序中的非法输入,编译器编译带类型的集合输入时会去掉带类型信息,是程序的运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样,由于编译器生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型几个中加入其他类型的数据,如:反射得到的集合,再调用add方法即可。
泛型中的术语:
整个ArrayList<E>为泛型类型
ArrayList<E>中的E称为类型变量和类型参数
ArrayList<Integer>称为参数化的类型
ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数
ArrayList<Integer>中的<>念typeof
ArrayList<>为原始类型
代码展示:
- /*没有用泛型*/
- ArrayList collection1=new ArrayList();
- collection1.add(1);
- collection1.add(1L);
- collection1.add("abc");
- //int i=(Integer)collection1.get(1);
- /*泛型修改上面代码*/
- ArrayList<String> collection2=new ArrayList<String>();
- // collection2.add(1);
- // collection2.add(1L);
- collection2.add("abc");
- String element=collection2.get(0);
- /*在反射中应用泛型*/
- //String str2=(String)constructor1.newInstance("abc");
- Constructor<String> constructor1=String.class.getConstructor(StringBuffer.class);
- String str2=constructor1.newInstance(new StringBuffer("abc"));//必须进行转换
- /*
- * Class.newInstance()方法
- * 该方法内部先得到默认的构造方法,在用得到的构造方法去创建实例对象
- */
- /*String obj=(String)Class.forName("abc").newInstance();*/
- System.out.println(str2.charAt(2)); //输出c
- ArrayList<Integer> collection3=new ArrayList<Integer>();
- System.out.println(collection3.getClass()==collection2.getClass());//true
- //collection3.add("abc");
- //透过编译器进行反射,JDK的特性,自动装箱功能
- collection3.getClass().getMethod("add", Object.class).invoke(collection3, "abc");
- System.out.println(collection3.get(0));//打印abc
泛型集合的综合实例:
- /*泛型集合的实例*/
- HashMap<String, Integer> maps=new HashMap<String, Integer>();
- maps.put("jzy", 20);
- maps.put("heima", 32);
- maps.put("cast", 30);
- Set<Map.Entry<String, Integer>> entrySet=maps.entrySet();
- for(Map.Entry<String, Integer> entry:entrySet)
- {
- System.out.println(entry.getKey()+":"+entry.getValue());
- }
自定义泛型:
public static <T> T add(T x,T y){return null;}
调用自定义的泛型:
add(3,5);
Number x2=add(3.25,6);--->这个是Number类型的
Object obj=add("abc",26);---->这个是Object类型
完成类型的交换:
- private static <T> void swap(T[] a,int i,int j){//T必须是引用类型
- T tmp=a[i];
- a[i]=a[j];
- a[j]=tmp;
- }
调用类型交换:
- swap(new String[] {"abc","xyz","itcast"},1,2);//传入三个字符串,并对第一个和第二个进行交换
- //swap(new int[] {1,2,3,4,5,5},3,4); //int[] 是一个数组对象,不能使用
注意:
1.在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。
2.当一个变量被声明为泛型时,只能被实例变量和方法调用(还有内嵌类型),而不能被静态变量和静态方法调用。
因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数。
泛型练习:
- /*采用自定义类型方法的方式打印任意参数化类型中的所有内容*/
- public static <T> void printCollection2(Collection<T> collection)
- {
- System.out.println(collection.size());
- for(Object obj:collection)
- {
- System.out.println(obj);
- }
- }
- /*定义一个方法,该方法打印任意参数类型的集合中的所有数据,需要用到通配符*/
- public static void printCollection(Collection<?> collection)
- {
- //collection.add("abc");//这句话会报错。。
- collection=new HashSet<Date>();//这句可以
- System.out.println(collection.size());
- for(Object obj:collection)
- {
- System.out.println(obj);
- }
- }
- /*定义一个方法,将任意类型的数组中的元素填充为某个相应的对象*/
- private static <T> void fillArray(T[] a,T obj){
- for(int i=0;i<a.length;i++){
- a[i]=obj;
- }
- }
- /*编写一个泛型方法,自动将Object类型转换为其他类型*/
- private static <T> T autoConvert(Object obj){
- return (T)obj;
- }
- /*通过反射获得实际类型的参数*/
- //Vector<Date> v1=new Vector<Date>();
- Method applyMethod=GenericTest.class.getMethod("applyVector", Vector.class);
- Type[] types=applyMethod.getGenericParameterTypes();
- //参数化类型
- ParameterizedType ptype=(ParameterizedType)types[0];
- System.out.println(ptype.getRawType());//得到原始的类型
- System.out.println(ptype.getActualTypeArguments()[0]);//得到实际类型参数
--------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com