Java反射机制用于帮助我们在运行时获取类的各种成分,包括包括字段,方法等。
并且可以在运行时实例化对象,调用方法,设置字段值等。
所有等java项目在编译后都会以.class文件的形式存在,.class文件承载了这个类型的全部信息
进而被ClassLoader加载到虚拟机中。
//知道到类名
Class<?> myObjectClass = className.class;
//已经得到对象
Person p = new Person();
Class<?> clazz = p.getClass();
//全类名
Class<?> clz = Class.forName("com.android.Person");
接口说明
public static Class<?> forName (String className)
// 全路径名,是否初始化对象,指定加载 ClassLoader.
public static Class<?> forName (String className, boolean shouldInitialize, ClassLoader classLoader)
private static void constructorReflect() {
try {
// 获取 Class 对象
Class<?> clz = Class.forName("com.android.Person");
// 获取带一个String参数的构造函数
Constructor<?> constructor = clz.getConstructor(String.class);
// 取消 Java 语言访问检查,一般用于反射私有成员
constructor.setAccessible(true);
// 创建对象
Object newInstance = constructor.newInstance("constructor");
System.out.println(" newInstance : " + newInstance.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
接口说明:
// 获取一个公有的构造函数,参数为可变参数,如果构造函数有参数,那么需要将参数的类型传递给 getConstructor 方法
public Constructor<T> getConstructor (Class...<?> parameterTypes)
// 获取目标类所有的公有构造函数
public Constructor[]<?> getConstructors ()
Person:
public class Person {
String mName;
public Person(String aName) {
mName = aName;
}
protected void printName(String s) {
System.out.println("My name is " + mName+s);
}
}
通过getDeclaredMethods 函数可以获取类中的所有方法,
getDeclaredMethod(String name, Class…
private static void reflectMethods() {
Person p = new Person("method");
Method[] methods = p.getClass().getDeclaredMethods();
for (Method method : methods) {
System.out.println("declared method name : " + method.getName());
}
try {
Method printName = p.getClass().getDeclaredMethod("printName", String.class);
// 获取方法的参数类型列表
Class<?>[] paramClasses = printName.getParameterTypes();
for (Class<?> clz : paramClasses) {
System.out.println("printName 的参数类型 : " + clz.getName());
}
System.out.println(printName.getName() + " is private "
+ Modifier.isPrivate(printName.getModifiers()));
//调用方法,
printName.invoke(p, "printName");
} catch (Exception e) {
e.printStackTrace();
}
}
接口说明:
// 函数名,参数类型列表 --> 获取指定函数名和参数的函数( 不包含从父类继承的函数 )
public Method getDeclaredMethod (String name, Class...<?> parameterTypes)
// 获取该 Class 对象中的所有函数( 不包含从父类继承的函数 )
public Method[] getDeclaredMethods ()
// 函数名,参数类型列表 --> 获取指定的 Class 对象中的 公有 函数( 包含从父类和接口类集成下来的函数 )
public Method getMethod (String name, Class...<?> parameterTypes)
// 获取该 Class 对象中的所有 公有 函数 ( 包含从父类和接口类集成下来的函数 )
public Method[] getMethods ()
和Method类似,把 getMethod 函数换成了 getField
接口说明:
// 属性名 --> 获取 Class 对象中指定属性名的属性( 不包含从父类继承的属性 )
public Method getDeclaredField (String name)
// 获取该 Class 对象中的所有属性( 不包含从父类继承的属性 )
public Method[] getDeclaredFields ()
// 属性名 --> 获取指定的 Class 对象中的**公有**属性,( 包含从父类和接口类集成下来的公有属性 )
public Method getField (String name)
// 获取该 Class 对象中的所有**公有**属性 ( 包含从父类和接口类集成下来的公有属性 )
public Method[] getFields ()
Class<?> superClass = p.getClass().getSuperclass();
//获取Class 对象的父类Class
Class<?>[] interfaceses = p.getClass().getInterfaces();
//获取 Class 对象中实现的接口。
//添加注解
@Test(tag = "Student class Test Annoatation")
public class Student extends Person implements Examination {
// 年级
@Test(tag = "mGrade Test Annotation ")
int mGrade;
// ......
}
//获取注解
private static void getAnnotationInfos() {
Student student = new Student("mr.simple");
Test classTest = student.getClass().getAnnotation(Test.class);
System.out.println("class Annotatation tag = " + classTest.tag());
Field field = null;
try {
field = student.getClass().getDeclaredField("mGrade");
Test testAnnotation = field.getAnnotation(Test.class);
System.out.println("属性的 Test 注解 tag : " + testAnnotation.tag());
} catch (Exception e) {
e.printStackTrace();
}
}
// 结果打印
class Annotatation tag = Student class Test Annoatation
属性的 Test 注解 tag : mGrade Test Annotation
接口说明:
// 获取指定类型的注解
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) ;
// 获取 Class 对象中的所有注解
public Annotation[] getAnnotations() ;
参考:公共技术点之 Java 反射 Reflection
反射工具类:调用方法,设置字段值(包括父类方法和字段)
public class ReflectUtil {
static class ReflectModel {
public String methodName;
public Class<?>[] paramClasses;
}
public static List<ReflectModel> getMethodNames(Class<?> clz) {
List<ReflectModel> result = new ArrayList<>();
Method[] declaredMethods = clz.getDeclaredMethods();
for (Method method : declaredMethods) {
ReflectModel reflectModel = new ReflectModel();
String methodName = method.getName();
Class<?>[] paramClasses = method.getParameterTypes();
reflectModel.methodName = methodName;
reflectModel.paramClasses = paramClasses;
result.add(reflectModel);
}
return result;
}
/** * 循环向上转型, 获取对象的 DeclaredMethod * * @param object : 子类对象 * @param methodName : 父类中的方法名 * @param parameterTypes : 父类中的方法参数类型 * @return 父类中的方法对象 */
public static Method getDeclaredMethod(Object object, String methodName, Class<?>... parameterTypes) {
Method method = null;
for (Class<?> clazz = object.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
try {
method = clazz.getDeclaredMethod(methodName, parameterTypes);
return method;
} catch (Exception e) {
//这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。
//如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了
}
}
return null;
}
public static Object invokeMethod(Object object, String methodName) {
//根据 对象、方法名和对应的方法参数 通过反射 调用上面的方法获取 Method 对象
Method method = getDeclaredMethod(object, methodName, null);
//抑制Java对方法进行检查,主要是针对私有方法而言
method.setAccessible(true);
try {
if (null != method) {
//调用object 的 method 所代表的方法,其方法的参数是 parameters
return method.invoke(object, null);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
/** * 直接调用对象方法, 而忽略修饰符(private, protected, default) * * @param object : 子类对象 * @param methodName : 父类中的方法名 * @param parameterTypes : 父类中的方法参数类型 * @param parameters : 父类中的方法参数 * @return 父类中方法的执行结果 */
public static Object invokeMethod(Object object, String methodName, Class<?>[] parameterTypes,
Object[] parameters) {
//根据 对象、方法名和对应的方法参数 通过反射 调用上面的方法获取 Method 对象
Method method = getDeclaredMethod(object, methodName, parameterTypes);
//抑制Java对方法进行检查,主要是针对私有方法而言
method.setAccessible(true);
try {
if (null != method) {
//调用object 的 method 所代表的方法,其方法的参数是 parameters
return method.invoke(object, parameters);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
/** * 循环向上转型, 获取对象的 DeclaredField * * @param object : 子类对象 * @param fieldName : 父类中的属性名 * @return 父类中的属性对象 */
public static Field getDeclaredField(Object object, String fieldName) {
Field field = null;
Class<?> clazz = object.getClass();
for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
try {
field = clazz.getDeclaredField(fieldName);
return field;
} catch (Exception e) {
//这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。
//如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了
}
}
return null;
}
/** * 直接设置对象属性值, 忽略 private/protected 修饰符, 也不经过 setter * * @param object : 子类对象 * @param fieldName : 父类中的属性名 * @param value : 将要设置的值 */
public static void setFieldValue(Object object, String fieldName, Object value) {
//根据 对象和属性名通过反射 调用上面的方法获取 Field对象
Field field = getDeclaredField(object, fieldName);
//抑制Java对其的检查
field.setAccessible(true);
try {
//将 object 中 field 所代表的值 设置为 value
field.set(object, value);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/** * 直接读取对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter * * @param object : 子类对象 * @param fieldName : 父类中的属性名 * @return : 父类中的属性值 */
public static Object getFieldValue(Object object, String fieldName) {
//根据 对象和属性名通过反射 调用上面的方法获取 Field对象
Field field = getDeclaredField(object, fieldName);
//抑制Java对其的检查
field.setAccessible(true);
try {
//获取 object 中 field 所代表的属性值
return field.get(object);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}