当我们声明了⼀个泛型的接⼝或类,或需要⼀个⼦类继承⾄这个泛型类,⽽我们⼜希望利⽤反射获取这些泛型参数信息。这就是本⽂将要介绍的ReflectionUtil就是为了解决这类问题的辅助⼯具类,为java.lang.reflect标准库的⼯具类。它提供了便捷的访问泛型对象类型(java.reflect.Type)的反射⽅法。
本⽂假设你已经了解java反射知识,并能熟练的应⽤。如果还不了解java反射知识,那么你可以先移步到,这可能是你开始学习反射的好起点.ReflectionUtil中包含以下⼏种功能:
1. 通过Type获取对象class;2. 通过Type创建对象;
3. 获取泛型对象的泛型化参数;
4. 检查对象是否存在默认构造函数;5. 获取指定类型中的特定field类型;
6. 获取指定类型中的特定method返回类型;7. 根据字符串标⽰获取枚举常量;8. ReflectionUtil下载地址.
通过Type获取对象class
private static final String TYPE_NAME_PREFIX = \"class \";
public static String getClassName(Type type) { if (type==null) { return \"\"; }
String className = type.toString();
if (className.startsWith(TYPE_NAME_PREFIX)) {
className = className.substring(TYPE_NAME_PREFIX.length()); }
return className;}
public static Class> getClass(Type type) throws ClassNotFoundException { String className = getClassName(type);
if (className==null || className.isEmpty()) { return null; }
return Class.forName(className);}
⽅法ReflectionUtil#getClass(Type)实现了从java.lang.reflect.Type获取java.lang.Class对象名称。这⾥利⽤了Type的toString⽅法获取所在类型的class。如“class some.package.Foo”,截取后部分class名称,在利⽤Class.forName(String)获取class对象。
通过Type创建对象
public static Object newInstance(Type type)
throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class> clazz = getClass(type); if (clazz==null) { return null; }
return clazz.newInstance();}
⽅法ReflectionUtil#newInstance(Type type)实现根据Type构造对象实例。在这⾥输⼊的Type不能是抽象类、接⼝、数组类型、以及基础类型、Void否则会发⽣InstantiationException异常。
获取泛型对象的泛型化参数
⾸先假设我们有如下两个对象:
public abstract class Foo public class FooChild extends Foo 怎么获取⼦类在Foo中传⼊的泛型Class类型呢? ⽐较常⽤的做法有以下两种: 强制FooChild传⼊⾃⼰的class类型(这也是⽐较常⽤的做法): public abstract class Foo //content} public class FooChild extends Foo super(FooChild.class); } //content} 利⽤反射获取: public static Type[] getParameterizedTypes(Object object) { Type superclassType = object.getClass().getGenericSuperclass(); if (!ParameterizedType.class.isAssignableFrom(superclassType.getClass())) { return null; } return ((ParameterizedType)superclassType).getActualTypeArguments();} ⽅法ReflectionUtil#getParameterizedTypes(Object)利⽤反射获取运⾏时泛型参数的类型,并数组的⽅式返回。本例中为返回⼀个T类型的Type数组。 为了Foo得到T的类型我们将会如下使⽤此⽅法: ... Type[] parameterizedTypes = ReflectionUtil.getParameterizedTypes(this);Class 注意: 在java.lang.reflect.ParameterizedType#getActualTypeArguments() documentation:的⽂档中你能看见如下⽂字: in some cases, the returned array can be empty. This can occur. if this type represents a non-parameterized type nested within a parameterized type. 当传⼊的对象为⾮泛型类型,则会返回空数组形式。 检查对象是否存在默认构造函数 public static boolean hasDefaultConstructor(Class> clazz) throws SecurityException { Class>[] empty = {}; try { clazz.getConstructor(empty); } catch (NoSuchMethodException e) { return false; } return true;} ⽅法ReflectionUtil#hasDefaultConstructor利⽤java.lang.reflect.Constructor检查是否存在默认的⽆参构造函数。 获取指定类型中的特定field类型 public static Class> getFieldClass(Class> clazz, String name) { if (clazz==null || name==null || name.isEmpty()) { return null;} name = name.toLowerCase();Class> propertyClass = null; for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); if (field.getName().equals(name)) { propertyClass = field.getType(); break; } } return propertyClass; } 在某些情况下你希望利⽤已知的类型信息和特定的字段名字想获取字段的类型,那么ReflectionUtil#getFieldClass(Class>, String)可以帮助你。ReflectionUtil#getFieldClass(Class>, String) 利⽤Class#getDeclaredFields()获取字段并循环⽐较java.lang.reflect.Field#getName()字段名称,返回字段所对应的类型对象。 获取指定类型中的特定method返回类型 public static Class> getMethodReturnType(Class> clazz, String name) { if (clazz==null || name==null || name.isEmpty()) { return null; } name = name.toLowerCase(); Class> returnType = null; for (Method method : clazz.getDeclaredMethods()) { if (method.getName().equals(name)) { returnType = method.getReturnType(); break; } } return returnType;} ⽅法ReflectionUtil#getMethodReturnType(Class>, String)可以帮助你根据对象类型和⽅法名称获取其所对应的⽅法返回类型。 ReflectionUtil#getMethodReturnType(Class>, String)利⽤Class#getDeclaredMethods()并以java.lang.reflect.Method#getName()⽐对⽅法名称,返回找到的⽅法的返回值类型(Method#getReturnType()). 根据字符串标⽰获取枚举常量 @SuppressWarnings({ \"unchecked\ public static Object getEnumConstant(Class> clazz, String name) { if (clazz==null || name==null || name.isEmpty()) { return null; } return Enum.valueOf((Class ⽅法ReflectionUtil#getEnumConstant(Class>, String)为利⽤制定的枚举类型和枚举名称获取其对象。这⾥的名称必须和存在的枚举常量匹配。 ReflectionUtil下载地址 你可以从这⾥下载. 原英⽂版地址: 因篇幅问题不能全部显示,请点此查看更多更全内容