Java中的泛型

来源:互联网 发布:有机器码破解软件 编辑:程序博客网 时间:2024/06/07 22:43

一、泛型简单应用

通过一个小例子看一下泛型的作用

package cn.itcast;import java.lang.reflect.Constructor;import java.util.ArrayList;public class Java_36_Generic {public static void main(String[] args) throws Exception {/*不添加泛型 */ArrayList collection1 = new ArrayList();collection1.add(1);collection1.add("abc");//取出时就要强制类型转换int i = (Integer)collection1.get(0);System.out.println(i);/*添加泛型 */ArrayList<String> collection2 = new ArrayList<String>();collection2.add("abc");//存放时只能放置String类型//取出时不用强制类型转换String str = collection2.get(0);/*泛型在反射的应用*/Constructor constructor1 = String.class.getConstructor(StringBuffer.class);String str1 = (String) constructor1.newInstance(new StringBuffer("abc"));Constructor<String> constructor2 = String.class.getConstructor(StringBuffer.class);String str2 = constructor2.newInstance(new StringBuffer("abc"));}}

通过以上可以得到:

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

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

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

二、泛型的作用

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

package cn.itcast;import java.util.ArrayList;public class Java_37_Generic {public static void main(String[] args) throws Exception {ArrayList<Integer> collection1 = new ArrayList<Integer>();ArrayList<String> collection2 = new ArrayList<String>();//创建的两个不同泛型的对象,指向同一份字节码文件System.out.println(collection1.getClass() == collection2.getClass());//true//跳过编译器,往<Integer>类型集合中添加String类型数据。collection1.getClass().getMethod("add", Object.class).invoke(collection1, "abc");System.out.println(collection1.get(0));//abc}}

三、泛型的语法

(1)ArrayList<E>类定义和ArrayList<Integer>类引用中设计如下术语:

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

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

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

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

ArrayList<Integer>中的<>念作typeof

ArrayList成为原始类型

(2)参数化类型与原始类型的兼容性

参数化类型可以引用一个原始类型的对象,编译器报警告

Collectionc = new Vector<String>();

原始类型可以引用一个参数化类型的对象,编译报告警告,例如:

Collectionc = new Vector<String>();

(3)参数化的类型不考虑继承关系:

Vector<String>v = new Vector<Object>();

Vector<Object>v = new Vector<String>();

(4)在创建数组实例时,数组的元素不能使用参数化的类型。

(5)泛型中的?通配符

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

package cn.itcast;import java.util.ArrayList;import java.util.Collection;public class Java_38_Generic {public static void main(String[] args) {//定义两个不同泛型的集合,并添加元素ArrayList<String> collection1 = new ArrayList<String>();ArrayList<Integer> collection2 = new ArrayList<Integer>();collection1.add("abc");collection2.add(1);collectionPrint(collection1);collectionPrint(collection2);}//定义集合输出方法private static void collectionPrint(Collection<?> cols) {for(Object obj : cols) {System.out.println(obj);}}}

②泛型中的?通配符扩展

限定通配符的上边界,如:

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

限定通配符的下边界,如:

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

注意:限定通配符总是包括自己。

四、泛型集合的综合应用案例

要求打印出HashMap集合中的所有元素。

package cn.itcast;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;public class Java_39_GenericDemo {public static void main(String[] args) {//定义一个HashMapMap<Integer, String> hashMap = new HashMap<Integer, String>();//向集合中添加元素hashMap.put(1, "zhangsan");hashMap.put(2, "lisi");hashMap.put(3, "wangwu");//通过EntrySet取出集合中的关系//注:Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set视图 Set<Map.Entry<Integer, String>> entrySet = hashMap.entrySet();//(1)通过增强for()迭代输出。for(Map.Entry<Integer, String> entry : entrySet)System.out.println("key:"+entry.getKey()+"\tvalue:"+entry.getValue());//(2)通过Interator迭代输出Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();while(it.hasNext()) {Map.Entry<Integer, String> me = it.next();System.out.println("key:"+me.getKey()+"\tvalue:"+me.getValue());}}}

通过以上对泛型有了初步的理解与掌握,在下一步的学习中进一步加强,

0 0
原创粉丝点击