现在的位置: 首页 > 综合 > 正文

黑马程序员 23 Java基础加强-05-泛型篇

2018年05月28日 ⁄ 综合 ⁄ 共 2884字 ⁄ 字号 评论关闭

               -------android培训java培训、期待与您交流!
----------



本日志doc文档下载



About 泛型

泛型是jdk1.5的所有新特性中最难深入掌握的部分,不过,我们在实际应用中不能掌握得那么深入,掌握泛型中一些最基本的内容就差不多了。

没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。使用泛型集合,可以将一个集合中的元素限定为一个特定类型,集合中只能存储同一个类型的对象,这样更安全;并且当从集合获取一个对象时,编译器也可以知道这个对象的类型,不需要对对象进行强制类型转换,这样更方便。

泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可。

Code1

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

array1.add(1);

array1.add(3);

//泛型是给编译器看的,运行时没有任何泛型的痕迹,可以利用"反射"给集合加入任何类型的值

array1.getClass().getMethod("add", Object.class).invoke(array1, "abc");

System.out.println(array1.get(2));

1、了解泛型

  1.1、ArrayList<E>类定义和ArrayList<Integer>类引用中涉及如下术语:

整个称为ArrayList<E>泛型类型

ArrayList<E>中的E称为类型变量或类型参数

整个ArrayList<Integer>称为参数化的类型

ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数

ArrayList<Integer>中的<>念着typeof

ArrayList称为原始类型

泛型中的类型参数严格说明集合中装载的数据类型是什么和可以加入什么类型的数据,记住:Collection<String>和Collection<Object>是两个没有转换关系的参数化的类型。

1.2、参数化类型与原始类型的兼容性:

参数化类型可以引用一个原始类型的对象,编译报告警告,例如,
Collection<String> c = new Vector();//可不可以,不就是编译器一句话的事吗?

原始类型可以引用一个参数化类型的对象,编译报告警告,例如,
Collection c = new Vector<String>();//原来的方法接受一个集合参数,新的类型也要能传进去

1.3、参数化类型不考虑类型参数的继承关系:

Vector<String> v = new Vector<Object>(); //错误!///不写<Object>没错,写了就是明知故犯

Vector<Object> v = new Vector<String>(); //也错误!

   假设Vector<String> v = new Vector<Object>();可以的话,那么以后从v中取出的对象当作String用,而v实际指向的对象中可以加入任意的类型对象;假设Vector<Object> v = new Vector<String>();可以的话,那么以后可以向v中加入任意的类型对象,而v实际指向的集合中只能装String类型的对象。

1.4、编译器不允许创建泛型变量的数组。即在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句有错误:

Vector<Integer> vectorList[] = new Vector<Integer>[10];

1.5、思考题:下面的代码会报错误吗?

Vector v1 = new Vector<String>();

Vector<Object> v = v1;

1.2、泛型中的?通配符

问题:定义一个方法,该方法用于打印出任意参数化类型的集合中的所有数据,该方法如何定义呢?

public static void printCollection(Collection<?> collection){

//collection.add("");//?通配符不确定具体参数化类型,不能往collection中增加值

System.out.println(collection.size());

for(Object object:collection){

System.out.println(object);

}

}

使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。

2.1、练习泛型的综合应用

Map<String, Integer> maps = new HashMap<String, Integer>();

maps.put("zxx", 95);

maps.put("lhm", 96);

maps.put("lsd", 97);

/*

 * Map.Entry<K, V> 映射项(键-值对)Map.entrySet 方法返回映射的 collection 视图,其中的元素属于此类

 * 获得映射项引用的唯一 方法是通过此 collection 视图的迭代器来实现。

*/

Set<Map.Entry<String, Integer>> entrySet = maps.entrySet();//返回此映射中包含的映射关系的 Set 视图

System.out.println("姓名\t成绩\t");

for(Map.Entry<String, Integer> entry:entrySet){

System.out.println(entry.getKey()+"\t"+entry.getValue());

}

2.2、通过反射获得泛型的参数化类型

System.out.println("---------------获取泛型中参数化类型的实际数据类型---------------------");

Method method = GenericTest.class.getMethod("applyVector", Vector.class);

Type [] types = method.getGenericParameterTypes();

ParameterizedType pType = (ParameterizedType) types[0];

System.out.println(types[0]);

System.out.println(pType.getRawType());//取原始类型

System.out.println(pType.getActualTypeArguments()[0]);//取实际类型

public static void applyVector(Vector<Date> v1){


}

抱歉!评论已关闭.