泛型类

  就是定义一个或者多个类型变量的类,实例如下:

package fanxingtest;

public class Dao <T>{

	private T first;
	private T second;
	public T getFirst() {
		return first;
	}
	public void setFirst(T first) {
		this.first = first;
	}
	public T getSecond() {
		return second;
	}
	public void setSecond(T second) {
		this.second = second;
	}
}

  Dao类引入一个类型变量T,该变量类型代表类中参数的类型,放在<>中。

泛型方法

  泛型方法只是在类中指定某一个或者多个方法的参数、返回值为泛型。

package fanxingtest;

public class CommonDao {

	public <T> T getMiddle(T...ts){
		return ts[0];
	}
}

  <T>标识该方法为泛型方法。

  T代表泛指类型。

泛型变量的限定

  在通过泛型进行数据操作时,部分操作需要借助于相关操作的指定类型。例如数值的加减操作需要继承Integer等类型操作。如下代码:

package fanxingtest;

public class CommonDao {
	
	public <T extends Integer> T max(T aT,T bT){
		if(aT.intValue()>bT.intValue())
			return aT;
		return bT;
	}
}

  T类型是一种指定继承Integer类的类型,该类型的变量将继承所有Integer类型的方法。

泛型代码和虚拟机

  在虚拟机中没有泛型类型对象,所有的对象都属于普通对象。在虚拟机中会将泛型类型中的变量转换为一种原始类型。如果泛型没有继承任何类型,只需将类中的变量转换为Object类型的变量。如果泛型继承某一基本类型,则将类中的变量替换为父类。如下:

package fanxingtest;

public class Dao <T>{

	private T first;
	private T second;
	public T getFirst() {
		return first;
	}
	public void setFirst(T first) {
		this.first = first;
	}
	public T getSecond() {
		return second;
	}
	public void setSecond(T second) {
		this.second = second;
	}
}

  在虚拟机中为

package fanxingtest;

public class Dao {

	private Object first;
	private Object second;
	public Object getFirst() {
		return first;
	}
	public void setFirst(Object first) {
		this.first = first;
	}
	public Object getSecond() {
		return second;
	}
	public void setSecond(Object second) {
		this.second = second;
	}
}

  带有约束的泛型类在虚拟机中会将泛型类型擦除,只保留父类

package fanxingtest;

public class Dao <T extends Integer>{

	private T first;
	private T second;
	public T getFirst() {
		return first;
	}
	public void setFirst(T first) {
		this.first = first;
	}
	public T getSecond() {
		return second;
	}
	public void setSecond(T second) {
		this.second = second;
	}
}

  在虚拟机中转换为如下代码

package fanxingtest;

public class Dao <Integer>{

	private Integer first;
	private Integer second;
	public Integer getFirst() {
		return first;
	}
	public void setFirst(Integer first) {
		this.first = first;
	}
	public Integer getSecond() {
		return second;
	}
	public void setSecond(Integer second) {
		this.second = second;
	}
}

  在泛型表达式中,在调用获取变量属性值时:1、调用get()方法,返回Object变量值。2、将Object变量转换为指定类型。

  在翻译泛型方法时可能会遇到以下继承关系:

package fanxingtest;

import java.util.Date;

public class DaoImpl extends Dao<Date>{

	public void setSecond(Date second){
		if(second.compareTo(getFirst())>=0){
			super.setSecond(second);
		}
	}
}

  在虚拟机中,会将擦除特殊类型,转换为:

package fanxingtest;

import java.util.Date;

public class DaoImpl extends Dao{

	public void setSecond(Date second){
		if(second.compareTo(getFirst())>=0){
			super.setSecond(second);
		}
	}
}

  在DaoImpl类中会生成一个setSecond(Object second){setSecond(Date second)}方法作为桥方法区调用setSecond(Date second),

约束和局限性

  1、不能用基本类型实例化类型参数,例如只有Dao<Integer>,而没有Dao<int>。

  2、不能创建参数化类型的数组,例如Dao<Integer> table = new Dao<Integer>[10]。

  3、不能实例化类型变量,如new T()。

  4、泛型类的静态上下文中类型变量无效。

  5、不能抛出或捕获泛型类的实例。

反射和泛型

  Class是一种泛型,String.Class是一个Class<String>类型的一个对象。

  Class<T>中的方法就使用了类型参数:

T newInstance()
T cast(Object obj)
T[] getEnumConstants()
Class<? super T> getSuperClass()
Constructor<T> getConstructor(Class... parameterTypes)
Constructor<T>  getDeclaredConstructor(Class... parameterTypes)

  newInstance()方法返回一个实例,这个实例有默认构造器获得。返回类型被声明为T。

  通过反射机制调用类中的方法。

  通过反射机制获取类中的属性。

  代码如下:

  1、泛型方法

package fanxingtest;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Dao {
	
	public <T> T helloWord(Class<T> clazz) throws Exception, SecurityException{
		Class<T> class1 = (Class<T>) clazz.getClass();
		//获取类中的作用域
		Field[] fields = clazz.getFields();
		//通过作用域名称获取单个作用域
		Field field = clazz.getField(fields[0].getName());
		//获取所有的方法
		Method[] method = clazz.getMethods();
		//对该类进行实例化对象
		T bean = clazz.newInstance();
		System.out.println("=======11111======"+class1.getName());
		System.out.println("=======22222======"+fields.length);
		System.out.println("=======33333======"+clazz.getName());
		System.out.println("=======44444======"+field.getName());
		System.out.println("=======55555======"+method.length);
		System.out.println("=======66666======"+method[0].getName());
		return bean;
	}
}

  2、具体类型定义

package fanxingtest;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

public class Group implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -3845465681582505505L;

	private String id;

	public String groupName;

	private int type;

	private String dissolveDate;

	private Date createDate;

	private Date updateDate;
	
	private Date groupUserChangeDate;
	
	private List<String> manager;
	
	private String creator;

	private List<String> person;
	
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getGroupName() {
		return groupName;
	}

	public void setGroupName(String groupName) {
		this.groupName = groupName;
	}

	public int getType() {
		return type;
	}

	public void setType(int type) {
		this.type = type;
	}

	public String getDissolveDate() {
		return dissolveDate;
	}

	public void setDissolveDate(String dissolveDate) {
		this.dissolveDate = dissolveDate;
	}

	public Date getCreateDate() {
		return createDate;
	}

	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}

	public Date getUpdateDate() {
		return updateDate;
	}

	public void setUpdateDate(Date updateDate) {
		this.updateDate = updateDate;
	}

	public List<String> getPerson() {
		return person;
	}

	public void setPerson(List<String> person) {
		this.person = person;
	}

	public Date getGroupUserChangeDate() {
		return groupUserChangeDate;
	}

	public void setGroupUserChangeDate(Date groupUserChangeDate) {
		this.groupUserChangeDate = groupUserChangeDate;
	}

	public List<String> getManager() {
		return manager;
	}

	public void setManager(List<String> manager) {
		this.manager = manager;
	}

	public String getCreator() {
		return creator;
	}

	public void setCreator(String creator) {
		this.creator = creator;
	}

}

  3、测试

package fanxingtest;

public class FanTest {

	public static void main(String[] args) throws SecurityException, Exception{
		Dao dao = new Dao();
		dao.helloWord(Group.class);
	}
}

  Method

  方法及其说明

  Class<?>[] getParameterTypes()
    按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。
  Class<?>[] getExceptionTypes()
    返回 Class 对象的数组,这些对象描述了声明将此 Method 对象表示的底层方法抛出的异常类型。
  Class<?> getReturnType()
    返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。

  Type[] getGenericParameterTypes()   
    按照声明顺序返回 Type 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型的。
  Type[] getGenericExceptionTypes()
    返回 Type 对象数组,这些对象描述了声明由此 Method 对象抛出的异常。
  Type getGenericReturnType()
    返回表示由此 Method 对象所表示方法的正式返回类型的 Type 对象。

  String getName()

    以 String 形式返回此 Method 对象表示的方法名称。

  TypeVariable<Method>[] getTypeParameters() 

    返回 TypeVariable 对象的数组,这些对象描述了由 GenericDeclaration 对象表示的一般声明按声明顺序来声明的类型变量。

  代码实例:

public <T> T methodInfo(Class<T> clazz) throws Exception, IllegalAccessException{
		Method[] method = clazz.getMethods();
		Method method1 = null;
		Method method2 = null;
		for(int i=0;i<method.length;i++){
			
			if(method[i].getName().equals("setManager")){
				method1 = method[i];
			}
			if(method[i].getName().equals("getManager")){
				method2 = method[i];
			}
		}
		Class reurnType = method1.getReturnType();
		System.out.println("=======11111======"+reurnType.getName());
		Class[] arguments = method1.getParameterTypes();
		System.out.println("=======22222======"+arguments[0].getName());
		Class reurnType2 = method2.getReturnType();
		System.out.println("=======33333======"+reurnType2.getName());
		T bean = clazz.newInstance();
		return bean;
	}

  

  Field

  Class<?> getType()

    返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。

  Type getGenericType()

    返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型。