背景
在很多编程场景中,我们需要指导某个对象是属于那个泛型类型的对象或者是那个泛型类型的子类对象,有时需要指导方法返回值对应的泛型参数实际什么类型,那么本工具类就可以方便的帮你解决以上问题。
代码实现
GenericsUtils.java
package com.mesnac.sys.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* 功能说明:泛型解析工具类
* 修改说明:
* @author 郑立兵 zhenglb@mesnac.com
* @date 2017-3-24 上午11:20:20
* @version V1.0
*/
public class GenericsUtils {
/***
* 定义字符集
*/
private static char[] chars = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'A', 'B','C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
'Z'}; //72个字符集
/***
* 通过反射,获得指定类的父类的泛型参数的实际类型
* @param clazz
* clazz 需要反射的类,改类必须继承泛型父类
* @param index
* 泛型参数所在索引,从0开始
* @return
* 泛型参数的实际类型,如果没有实现ParameterizedType接口,即不支持泛型,则直接返回<code>Object.class</code>
*/
@SuppressWarnings("rawtypes")
public static Class getSupperClassGenericType(Class clazz, int index) {
//得到泛型父类
Type genType = clazz.getGenericSuperclass();
//如果没有实现ParameterizedType接口,即不支持泛型,直接返回Object.class
if (!(genType instanceof ParameterizedType)) {
return Object.class;
}
//返回表示此类型实际类型参数的Type对象的数组,数组里放的都是对应类型的Class,如BuyerServiceBean extends DaoSupport<Buyer,Contact>就返回Buyer和Contact类型
Type[] params = ((ParameterizedType)genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
throw new RuntimeException("你输入的索引" + (index < 0 ? "不能小于0" : "超出了参数的总数"));
}
if (!(params[index] instanceof Class)) {
return Object.class;
}
return (Class)params[index];
}
/***
* 通过反射,获得指定类的父类的泛型参数的实际类型
* @param clazz
* clazz 需要反射的类,改类必须继承泛型父类
* @return
* 泛型参数的实际类型,如果没有实现ParameterizedType接口,即不支持泛型,则直接返回<code>Object.class</code>
*/
@SuppressWarnings("rawtypes")
public static Class getSupperClassGenericType(Class clazz) {
return getSupperClassGenericType(clazz, 0);
}
/***
* 通过反射,获得方法返回值泛型参数的实际类型. 如: public Map<String, Buyer> getNames(){}
* @param method
* method 方法
* @param index
* 泛型参数所在索引,从0开始。
* @return
* 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,则直接返回<code>Object.class</code>
*/
@SuppressWarnings("rawtypes")
public static Class getMethodGenericReturnType(Method method, int index) {
Type returnType = method.getGenericReturnType();
if (returnType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType) returnType;
Type[] typeArguments = type.getActualTypeArguments();
if (index >= typeArguments.length || index < 0) {
throw new RuntimeException("你输入的索引" + (index < 0 ? "不能小于0" : "超出了参数的总数"));
}
return (Class) typeArguments[index];
}
return Object.class;
}
/***
* 通过反射,获得方法返回值泛型参数的实际类型. 如: public Map<String, Buyer> getNames(){}
* @param method
* method 方法
* @return
* 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,则直接返回<code>Object.class</code>
*/
@SuppressWarnings("rawtypes")
public static Class getMethodGenericReturnType(Method method) {
return getMethodGenericReturnType(method, 0);
}
/***
* 通过反射,获得方法输入参数第index个输入参数的所有泛型参数的实际类型. 如: public void add(Map<String, Buyer> maps, List<String> names) {}
* @param method
* method 方法
* @param index
* 第几个输入参数
* @return
* 输入参数的泛型参数的实际类型集合, 如果没有实现ParameterizedType接口,即不支持泛型,则直接返回空集合
*/
@SuppressWarnings("rawtypes")
public static List<Class> getMethodGenericParameterTypes(Method method, int index) {
List<Class> results = new ArrayList<Class>();
Type[] genericParameterTypes = method.getGenericParameterTypes();
if (index >= genericParameterTypes.length || index < 0) {
throw new RuntimeException("你输入的索引" + (index < 0 ? "不能小于0" : "超出了参数的总数"));
}
Type genericParameterType = genericParameterTypes[index];
if (genericParameterType instanceof ParameterizedType) {
ParameterizedType aType = (ParameterizedType) genericParameterType;
Type[] parameterArgTypes = aType.getActualTypeArguments();
for (Type parameterArgType : parameterArgTypes) {
Class parameterArgClass = (Class) parameterArgType;
results.add(parameterArgClass);
}
return results;
}
return results;
}
/***
* 通过反射,获得方法输入参数第index个输入参数的所有泛型参数的实际类型. 如: public void add(Map<String, Buyer> maps, List<String> names) {}
* @param method
* method 方法
* @return
* 输入参数的泛型参数的实际类型集合, 如果没有实现ParameterizedType接口,即不支持泛型,则直接返回空集合
*/
@SuppressWarnings("rawtypes")
public static List<Class> getMethodGenericParameterTypes(Method method) {
return getMethodGenericParameterTypes(method, 0);
}
/***
* 通过反射,获得Field泛型参数的实际类型. 如: public Map<String, Buyer> names;
* @param field
* field 字段
* @param index
* 泛型参数所在索引,从0开始。
* @return
* 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,则直接返回<code>Object.class</code>
*/
public static Class getFieldGenericType(Field field, int index) {
Type genericFieldType = field.getGenericType();
if (genericFieldType instanceof ParameterizedType) {
ParameterizedType aType = (ParameterizedType) genericFieldType;
Type[] fieldArgTypes = aType.getActualTypeArguments();
if (index >= fieldArgTypes.length || index < 0) {
throw new RuntimeException("你输入的索引" + (index < 0 ? "不能小于0" : "超出了参数的总数"));
}
return (Class) fieldArgTypes[index];
}
return Object.class;
}
/***
* 通过反射,获得Field泛型参数的实际类型. 如: public Map<String, Buyer> names;
* @param field
* field 字段
* @return
* 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,则直接返回<code>Object.class</code>
*/
public static Class getFieldGenericType(Field field) {
return getFieldGenericType(field, 0);
}
/***
* 根据实体得到实体的所有属性
* @param objClass
* @return
* @throws ClassNotFoundException
*/
public static String[] getColumnNames(String objClass) throws ClassNotFoundException {
String[] wageStrArray = null;
if (objClass != null) {
Class class1 = Class.forName(objClass);
Field[] field = class1.getDeclaredFields();// 这里便是获得实体Bean中所有属性的方法
StringBuffer sb = new StringBuffer();
for (int i = 0; i < field.length; i++) {// 这里不多说了
sb.append(field[i].getName());
// 这是分割符 是为了去掉最后那个逗号
// 比如 如果不去最后那个逗号 最后打印出来的结果是 "id,name,"
// 去了以后打印出来的是 "id,name"
if (i < field.length - 1) {
sb.append(",");
}
}
// split(",");这是根据逗号来切割字符串使字符串变成一个数组
wageStrArray = sb.toString().split(",");
return wageStrArray;
} else {
return wageStrArray;
}
}
public static Object[] field2Value(Field[] f, Object o) throws Exception {
Object[] value = new Object[f.length];
for (int i = 0; i < f.length; i++) {
value[i] = f[i].get(o);
}
return value;
}
// public HttpSession getSession() {
// HttpSession session=null;
// ServletRequestAttributes attr = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
// HttpSession contextSess = attr == null ? session : attr.getRequest().getSession(true);
// return contextSess;
// }
/***
* 得到实体类
* @param objClass
* 实体类包含包名
* @return
*/
public static Class getEntityClass(String objClass) {
Class entityClass = null;
try {
entityClass = Class.forName(objClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return entityClass;
}
/***
* 生成指定长度的随机密码
* @param passLength
* 随机密码的长度
* @return
* 返回生成的随机密码字符串
*/
public static String getPasswords(int passLength) {
String passwords = "";// 新建一个长度为指定需要密码个数的字符串数组
Random random = new Random();
StringBuilder password = new StringBuilder("");// 保存生成密码的变量
for (int m = 1; m <= passLength; m++) {// 内循环 从1开始到密码长度 正式开始生成密码
password.append(chars[random.nextInt(62)]);// 为密码变量随机增加上面字符中的一个
}
passwords = password.toString();// 将生成出来的密码赋值给密码数组
return passwords;
}
}