自从java支持泛型后,现在,spring生态中的框架及目前的应用都使用了泛型。有的框架如mybatis和spring都需要反射获取类型,以使得序列化和反序列化得以实现,但有时候我们根据项目的需要获取这些具体类型。
比如,mybatis orm环境下,数据库字段类型和java类型不匹配检测的功能,需要利用这种方法获取类中方法的具体类型,结合com.mysql.cj.MysqlType枚举中类型的映射关系列出不匹配的实例、表、java类型、数据库列、java属性字段等信息。【为什么要检测呢,因为近期看到由于账号id java类型为Long,而数据库类型为int,导致故障发生)
为了能得到类中方法的泛型参数具体类型或者返回的泛型参数具体类型,我们必须使用反射及类型ParameterizedType。
java类型的鼻祖类是java.lang.reflect.Type,这个类型包括了原生类型、泛型类型、数组类型等等。
/**
* Type is the common superinterface for all types in the Java
* programming language. These include raw types, parameterized types,
* array types, type variables and primitive types.
*
* @since 1.5
*/
public interface Type {
/**
* Returns a string describing this type, including information
* about any type parameters.
*
* @implSpec The default implementation calls {@code toString}.
*
* @return a string describing this type
* @since 1.8
*/
default String getTypeName() {
return toString();
}
}
在反射使用过程中,我们必须根据具体的类型来采取不同的策略,那么就需要关系type类的所有子类型:
其中,第二个子类ParameterizedType就是本文所要使用的。
例如;
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.stream.Stream;
/**
* @author sdcuike
* @DATE 2019/9/30
*/
public class Demo {
public static void main(String[] args) throws NoSuchMethodException {
Method method = DemoInterface.class.getDeclaredMethod("demo", List.class);
//返回类型解析
Type returnType = method.getGenericReturnType();
// if (returnType instanceof Class) {
// System.out.println("返回类型(不是泛型:" + returnType);
// System.out.println();
// }
if (returnType instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) returnType;
System.out.print("返回泛型类型:");
Stream.of(pType.getActualTypeArguments()).forEach(System.out::print);
System.out.println();
}
//参数类型解析
List<Object> parameters = new ArrayList<>();
Type[] types = method.getGenericParameterTypes();
for (Type type : types) {
// if (type instanceof Class) {
// parameters.add(type);
// }
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) type;
Stream.of(pType.getActualTypeArguments()).forEach(t -> parameters.add("泛型参数" + t));
}
}
System.out.println("参数:" + parameters);
}
interface DemoInterface {
List<String> demo(List<Long> ids);
}
}
根据具体类型,强制类型转换后就可以获得这些具体的参数了类型。
输出:
返回泛型类型:class java.lang.String
参数:[泛型参数class java.lang.Long]