黑马程序员—Java基础加强—(泛型)

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

1.泛型概述

泛型是JDK1.5版本以后出现的新特性,用于解决安全问题,是一个类型安全机制。

类的后面跟着<E>这样的标识,如Vector<E>ArrayList<E>等,这个<E>标识就代表泛型。
其本质就是实现参数化类型,也就是说所操作的数据类型被指定为一个参数。

好处:
1
、将运行时期出现的问题 ClassCastException 转移到了编译时期,方便程序员解决,让运行时期问题减少。
2
、避免了强制转换麻烦。

import java.util.*;  
 	class GenericDemo{  
 	    public static void main(String[] args){  
 	        //定义了一个String类型的数组列表  
 	        ArrayList<String> al = new ArrayList<String>();  
 	        al.add("abc002");  
 	        al.add("abc013");  
 	        al.add("abc256");  
 	        al.add("abc028");  
 	          
 	        //al.add(4);//al.add(new Integer(5));  
 	          
 	        //迭代器要使用泛型  
 	        Iterator<String> it = al.iterator();  
 	        while(it.hasNext()){  
 	            String s = it.next();  
 	            System.out.println(s);  
 	        }  
 	    }  
 	}  
 	/* 
 	结果 
 	abc002 
 	abc013 
 	abc256 
 	abc028 
 	*/

2.泛型通配符:

? 泛型的通配符,也叫占位符

import java.util.ArrayList;
import java.util.Collection;
import java.util.Vector;

public class GenerticTest {
	
	
	public static void main(String[] args) throws Exception{
		ArrayList<String> al=new ArrayList<String>();
		
		
		printCollection1(al);//正确
//		printCollection(al);// 错误,无法将ArrayList<String>与Collection<Object>进行匹配
	}
	//需求:一个能将装着不同类型元素的集合打印出来
	public static void printCollection(Collection<Object> collection){
		collection.add("abc");//不会报错,因为String为Obeject的子类
		for(Object obj:collection){
			System.out.println(obj);
		}
	}
	public static void printCollection1(Collection<?> collection){
//		collection.add("abc");//报错,用通配符后无法使用与类型有关的特有方法
		collection.size();
		
		for(Object obj:collection){
			System.out.println(obj);
		}	
	}
	
}

3.泛型限定:

上限:<? extends E> 可以接受E类型或者E的子类型。
下限:<? super E> 可以接收E类型或者E的父类型

4.自定义泛型方法:

当一个方法的返回值类型或参数类型无法确定时,可以使用自定义类型代替。格式为将自定义类型定义在方法的返回值类型前用<>表示。如:
public static <T>void(T t){}


类型推断:如上例子,自定义泛型类型T后,JVM会根据调用时传入的实际参数类型,将T推断为各个实例参数的最大交集。

类型范围:只有引用数据类型才能作为泛型方法的实际参数类型

例子如下:

package it.cast.day2;

import java.util.Arrays;

//自定义泛型方法
public class GenerticTest1 {
	public static void main(String[] args){
		String[] stra=new String[]{"s","g","ag","ok"};
		int[] inta={1,3,7,68,6};
		swap(stra,1,2);
//		swap(inta,0,2);//此处报错,因为只有引用数据类型才能作为泛型方法的实际参数类型(T)。
		System.out.println(Arrays.asList(stra));
	}
	public static <T>void swap(T[] t,int a,int b){//自定义泛型方法
	T temp=t[a];
	t[a]=t[b];
	t[b]=temp;
	}
}

注:

1:使用范围:普通方法、构造方法和静态方法中都可以使用泛型。

2.也可以用类型变量表示异常,成为参数化的异常,可以用于方法的throw列表中,但是不能用于catch子句中。

3.在反省中可以同时有多个类型参数,在定义他们的<>中用逗号分开,例如:

public static <K,V> getValue(K key){return map.get(Key k)}

5.自定义泛型类型:

如果类的对象中的多出都要用到同一个泛型参数,即这些地方引用的泛型类型要保持同一实际类型时,这个时候就要蚕蛹泛型类型的方式定义,也就是类级别的泛型,语法格式如下:

public class GenericDao<T>{
	priavate Tfield1;
	public void save(T obj){}
	public T getByld(int id){}
}


注:当一个变量被声明为泛型时,只能被实例变量和方法调用(还有内嵌类型),而不能被静态变量和静态方法调用,以为静态成员是被所有参数话的类所共享的,所以静态成员不应该有类级别的类型参数。如果静态方法确实需要泛型,可将其定义在静态方法自身上。

6.通过反射获得泛型的参数化类型:

需求:通过反射获取泛型类型中的实际化参数,如Vector<Date>所装的到底是什么元素
思路:

1.直接通过反射Vector的字节码文件,无法获得其具体参数类型,因为其字节码文件是去泛型化的,通过以下示例说明:

public class GenerticTest {
	
	
	public static void main(String[] args) throws Exception{
		ArrayList<String> al=new ArrayList<String>();
		al.add("asdf");
		al.getClass().getMethod("add",Object.class).invoke(al, 6);
		System.out.println(al);
		//打印结果为[asdf, 6]说明将6已经添加入al中
	}
}


 2.Method类中有方法可以获得带泛型的参数列表,如果将Vector<Date>作为参数传入某方法,即可以在其字节码文件中保留其泛型类型,具体例子如下:
 

package it.cast.day2;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import java.util.Date;
import java.util.Vector;

public class GenerticTest3 {
	public static void getVetorType(Vector<Date> v1){
		
	}
	public static void main(String[] args) throws NoSuchMethodException, SecurityException{
		Type[] type=GenerticTest3.class.getMethod("getVetorType", Vector.class).getGenericParameterTypes();/*
		获得getVetorType方法中带泛型类型的参数列表*/
		ParameterizedType ptype=(ParameterizedType)type[0];//将参数类型列表中第一个类型参数,强制转换为其具体子类
		
		System.out.println(ptype.getActualTypeArguments()[0]);/*打印表示Vector<Date>此类型实际类型参数的 Type 对象
		的数组的第一个元素*/
		
		System.out.println(ptype.getRawType());//打印表示声明此类型的类或接口
		/*输出结果为class java.util.Date 
		class java.util.Vector*/
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值