Java中的泛型

一、泛型简单应用

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

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) {
		//定义一个HashMap
		Map<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());
		}		
	}
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值