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