黑马程序员------Java的泛型(原理应用、自定义泛型)

来源:互联网 发布:梵高怎么得的精神 知乎 编辑:程序博客网 时间:2024/06/05 08:03

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

 

微笑泛型

 

没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。使用泛型集合,

可以将一个集合中的元素限定为一个特定类型,集合中只能存储同一个类型的对象,这样更安全,并

且从集合获取一个对象时,编译器也可以知道这个对象的类型,不需要对对象进行强制转换。

 

泛型是提供给Javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,

编译器编译带类型说明的集合时会去除掉“类型”信息,但程序运行效率不受影响,对于参数化的泛

型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信

息,只要能跳过编译器,就可以往某个泛型集合中加入其他类型的数据,例如,用反射得到集合,再

调用其add方法即可。

 

package com.lee.demo;import java.lang.reflect.Method;import java.util.ArrayList;public class GenericTest {/** * @param args */public static void main(String[] args) throws Exception{// TODO Auto-generated method stubArrayList<Integer> list = new ArrayList<Integer>();//list.add("abc");编译不能通过list.add(1);list.add(2);list.add(3);System.out.println(list.get(1));//利用反射,跳过编译器存入String对象Class clazz = list.getClass();Method addMethod = clazz.getMethod("add", Object.class);addMethod.invoke(list, "xyz");System.out.println(list.get(3));}}


泛型的通配符扩展应用

 

package com.lee.demo;import java.util.ArrayList;import java.util.Collection;public class GenericTest1 {/** * @param args */public static void main(String[] args) throws Exception{// TODO Auto-generated method stubArrayList<Integer> list = new ArrayList<Integer>();//list.add("abc");编译不能通过list.add(1);list.add(2);list.add(3);//sopCollection_0(list);编译失败sopCollection_1(list);}public static void sopCollection_0(Collection<Object> collection){//collection.add(1);由于无法确定?类型,编译失败System.out.println(collection.size());}public static void sopCollection_1(Collection<?> collection){//collection.add(1);由于无法确定?类型,编译失败System.out.println(collection.size());}}

总结:

使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,

可以调用与参数化无关的方法,不能调用与参数化有关的方法

限定通配符的上边界:

正确:Vector<? extends Number> x = new Vector<Integer>();

错误:Vector<? extends Number> x = new Vector<String>();

 

限定通配符的下边界:

正确:Vector<? super Integer> x = new Vector<Number>();

错误:Vector<? super Integer> x = new Vector<Byte>();

提示:限定符总是包括自己。

泛型集合的综合应用:

package com.lee.demo;import java.util.HashMap;import java.util.Map;import java.util.Set;public class GenericTest2 {/** * @param args */public static void main(String[] args) throws Exception{// TODO Auto-generated method stubHashMap<String,Integer> maps = new HashMap<String, Integer>();maps.put("Tom", 12);maps.put("Kate", 15);maps.put("Hanmei", 13);Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();for(Map.Entry<String,Integer> me:entrySet){System.out.println(me.getKey()+":"+me.getValue());}}}


微笑自定义泛型

 

  自定义泛型方法

package com.lee.demo;public class GenericTest2 {/** * @param args */public static void main(String[] args) throws Exception{// TODO Auto-generated method stubNumber x = add(3,3.5);Object y = add(3,"das");swap(new String[]{"ad","lee","dsa"}, 1, 2);//只有引用类型才能作为泛型的实际参数。//swap(new int[]{1,5,8},1,2);编译失败swap(new Integer[]{1,5,8},1,2);}public static <T> T add(T x,T y){return null;}public static <T> void swap(T[] a,int i,int j){T tmp = a[i];a[i] = a[j];a[j] = tmp;}}

 

普通方法、构造方法和静态方法中都可以用泛型。编译器也不允许创建类型变量的数组。

也可以用类型变量表示异常,称为参数化的异常,可以用于方法的throws列表中,但不

能存在catch子句中。

自定义泛型类

 

如果类的实例对象中的多处要用到同一个泛型参数,即这些地方引用的泛型方法要保持

同一个实际类型时,这时候就要采用泛型类型的方式进行定义,也就是类级别的泛型,

语法格式:

public class GenericDao <T>{

  private T field1;

 public void sava(T obj){}

  public T getById(int id){}

}

 

类级别的泛型是根据引用该类名时指定的类型信息来参数化类型变量的,例如

GenericDao<String> dao = null;

new gennericDao<String>();

 

注意:

1.在泛型类型进行参数化时,类型参数的实例必须是引用类型,不嫩是基本类型。

2.当一个变量被声明为泛型时,只能被实例变量和方法调用,而不能被静态变量和静态方法调用。

因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数

 

通过反射获得泛型的实际类型参数

 

package com.lee.demo;import java.lang.reflect.Method;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.util.Date;import java.util.Vector;public class GenericTest3 {/** * @param args */public static void main(String[] args) throws Exception{// TODO Auto-generated method stubClass clazz = GenericTest3.class;Method applyMethod = (Method)clazz.getMethod("applyMethod",Vector.class);//得到参数类型Type[] types = applyMethod.getGenericParameterTypes();ParameterizedType pType = (ParameterizedType)types[0];//原始类型  class java.util.VectorSystem.out.println(pType.getRawType());//得到实际参数类型  class java.util.DateSystem.out.println(pType.getActualTypeArguments()[0]);}public static void applyMethod(Vector<Date> v1){}}

 

 

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

详情请查看:http://edu.csdn.net

 

原创粉丝点击