黑马程序员-java基础加强-JDK1.5新特性-泛型

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

JDK1.5新特性:泛型

泛型定义
泛型用<>来表示,来限定某一个容器装入的元素类型。<>里面填入的是元素的类型
------------------------------------------------------------------------
集合运用泛型之后的叫法
ArrayList<E> :泛型类型,E称为类型变量或者类型参数,E只能是引用数据类型,不能是
基本数类型。
ArrayList<Integer> :参数化的类型,Integer称为类型参数的实例
ArrayList:原始类型
<>:typeof  ArrayList<Integer> 读作,ArrayList typeof Integer
------------------------------------------------------------------------
泛型的<>内的类型限定的几种情况
a、<>里面直接填入元素的类型,
如,ArrayList<Integer> al=new ArrayList<Integer>();
注意:
第一:参数化类型可以引用一个原始类型的对象,
Collection<String> collection =new ArrayList();
第二:原始类型可以引用一个参数化类型
Collection collection =new ArrayList<String>();
第三:参数化类型不考虑类型参数的继承关系:
Vector<String> v=new Vector<Object>();
Vector<Object> v=new Vector<String>();//都是不对的。
第四:创建数组实例时,数组的元素不能使用参数化的类型
Vector<String> vector[]=new Vector<String>[10];//这是错的。
b、<>里面写入?,即写入通配符。它的特点
第一:? 通配符为一个具体的类型,但是可以指向任意的类型。
如:Collection<?> collection=new ArrayList<Integer>();
第二:当一个容器使用的是通配符时,则此容器就不能使用与类型有关的方法
如,add(E e)方法。因为对于此容器,并不知道它具体的指向什么参数化类型的容器
所以并不能使用与类型有关的方法。
ArrayList<?> al2=new ArrayList<Integer>();
   al2.add(1);//不对。
第三:只能是Vector<?> v=new Vector<String>();而不能是Vector<String> v=new Vector<?>();
即通配符只能在左边不能在右边,即?通配符定义的变量主要用来用作引用。
总结:使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用来用作
引用,可以调用与参数无关的方法,不能调用与参数有关的方法。

练习:定义一个方法,用于打印任意参数化类型的集合中的所有数据。

                package cn.itcast.day2;
		import java.lang.reflect.Method;
		import java.util.ArrayList;
		import java.util.Collection;
		public class FanXingTest {
			public static void main(String[] args)throws Exception {
				// TODO Auto-generated method stub
				ArrayList<Integer> al=new ArrayList<Integer>();
				al.add(1);
				al.add(2);
				al.add(3);
				printElem(al);
			}
			//通过通配符来达到“打印任意参数化类型集合元素”的要求。
			public static void printElem(Collection<?> collection)throws Exception{
				System.out.println("未添加元素之前的size:"+collection.size());
				//不能直接调用collection.add("abc");可以利用反射来跳过编译器来添加元素
				Method method = collection.getClass().getMethod("add", Object.class);
				method.invoke(collection, "abc");
				//可以调用与参数无关的方法
				System.out.println("添加元素之后的size:"+collection.size());
				//打印此集合中的元素
				for (Object object : collection) {
					System.out.println(object);	
				}	
			}
		}
c、向上限定
格式:<? extends Number>表示只能为Number的子类或者Number
Vector<? extends Number> v=new Vector<Integer>();//对的
Vector<? extends Number> v=new Vector<String>();//错的
Number的子类为7中基本类型的引用类型表示形式,即为Byte,Short,Integer,Boolean
,Float,Double,Character。
d、向下限定
格式:<? super Integer>表示只能为Integer或者Integer的子类
Vector<? super Integer> v=new Vector<Number>();//对的
Vector<? super Integer> v=new Vector<Byte();//错的,因为Integer和Byte是平级的。
-------------------------------------------------------------------------

泛型原理
泛型只是给编译器看的,即当编译之后,class文件中不再有相关的泛型信息。
所以对于给定的参数化类型的集合,要想对它里面添加别的类型的元素,只需
要跳过编译器即可。
例子:

                package cn.itcast.day2;
		import java.lang.reflect.Method;
		import java.util.ArrayList;
		import java.util.Collection;
		public class FanXingTest2 {
			public static void main(String[] args) throws Exception{
				// TODO Auto-generated method stub
				Collection<Integer> collection=new ArrayList<Integer>();
				//通过反射获得方法add
				Method method=collection.getClass().getMethod("add",Object.class);
				//利用反射得到的方法来想集合中添加元素
				method.invoke(collection,"abc");
				method.invoke(collection,1);
				System.out.println(collection.size());
				for (Object integer : collection) {
					System.out.println(integer);	
				}
			}
		}
------------------------------------------------------------------------
自定义泛型方法
1、即在方法的返回值类型前面上加上<>来自定义泛型方法
例子:
public static <T> void swap(T[] arr,int x,int y)
{
T temp=arr[x];
arr[x]=arr[y];
arr[y]=temp;
}
2、泛型可以定义在类上、方法上、构造方法上、静态方法上、和异常上。
定义在异常上:
private static <T extends Exception> void sayHello()throws T
{
try
{
}
catch (Exception e)//注意此处捕捉异常必须是具体的异常,不能写成
//T e
{
throw(T)e;
}
}
3、泛型也可以写成<V extends 接口1&接口2>即表示V是实现了接口1和接口2的类或者它的子类。
4、在泛型中可以同时有多个类型参数,在定义他们时在尖括号中用逗号隔开
public static <K,V> V getValue(K key)
{
return map.get(key);
}
5、类型参数的类型推断
a、若:static <E> void swap(E[] a,int x,int y),只有一处用到,则类型直接由调用此方法
时传递的参数类型或者返回值来决定泛型参数的类型。
b、static <T> T add(T a,T b),即多处用到了类型变量,则若几处都对应同一种类型,则就确定为
此类型。
c、若,static <T> void fill(T[] A,T v).多处用到且这几处对应不同的类型,且无使用返回值,这时
取多个参数中的最大交集类型,eg fill(new Integer[3],3.5f),则对应Number。
d、若,static <T> T add(T a,T b);多处用到,且这几处对应不同的类型,且有返回值类型,则优先考虑
返回值类型。int x=add(3,3.5f);若返回值不对再试别的。最后应该确定为Number类型。
------------------------------------------------------------------------
自定义泛型类
1、作用:将泛型定义在类上,来达到类中的所有方法操作同一个类型。
例子:

               class FanXing<T>
		{
			public T get(int x)
			{
				return null;
			}
			public void delete(T x)
			{
			}
			public void update(T obj)
			{
			}
			//即对于静态方法不能使用类上的泛型变量。
			public static <E> E getclass(E e)
			{
				return null;
			}
		}
------------------------------------------------------------------------
练习:

1、获取HashMap集合中的元素

        package cn.itcast.day2;
	import java.util.HashMap;
	import java.util.Map;
	import java.util.Set;
	public class HashMapFan {
		public static void main(String[] args) {
			// TODO Auto-generated method stub
			HashMap<String,Integer> hm=new HashMap<String,Integer>();
			hm.put("a",1);
			hm.put("b",1);
			hm.put("c",1);
			hm.put("d",1);
			Set<Map.Entry<String,Integer>> set=hm.entrySet();
			for (Map.Entry<String,Integer> me : set) {
				System.out.println(me.getKey()+":::"+me.getValue());	
			}
		}
	}
2、通过反射获得泛型的实际类型参数
分析:要想得到泛型的实际类型参数,即得到Vector<Integer> v=new Vector<Integer>()  
中的Integer则通过v是没办法得到此实际类型参数的,因为当编译器一编译完,泛型就没了。
那么可以通过,public static void applyFan(Vector<Integer> v1){}这样的方法来得到
此方法里面的参数的类型,从而得到实际类型参数。
代码:

                package cn.itcast.day2;
		import java.lang.reflect.Method;
		import java.lang.reflect.ParameterizedType;
		import java.lang.reflect.Type;
		import java.util.Vector;
		public class ReflectFan {
			public static void main(String[] args)throws Exception {
				// TODO Auto-generated method stub
				//通过反射得到此方法
				Method method =ReflectFan.class.getMethod("applyVector", Vector.class);
				//通过调用方法getGenericParameterTypes()来得到此方法的泛型参数类型。
				Type[] types=method.getGenericParameterTypes();
				//得到此参数的参数类型。
				ParameterizedType pType=(ParameterizedType)types[0];
				System.out.println(pType.getRawType());//class java.util.Vector
				//下面结果为class java.lang.Integer
				System.out.println(pType.getActualTypeArguments()[0]);	
			}
			public static void applyVector(Vector<Integer> v){
				
			}
		}

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


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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章