泛型类
就是定义一个或者多个类型变量的类,实例如下:
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 对象所表示字段的声明类型。