Java反射机制

概述

Java反射机制用于帮助我们在运行时获取类的各种成分,包括包括字段,方法等。
并且可以在运行时实例化对象,调用方法,设置字段值等。
所有等java项目在编译后都会以.class文件的形式存在,.class文件承载了这个类型的全部信息
进而被ClassLoader加载到虚拟机中。

Class

//知道到类名
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)

Constructor

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);
    }
}

Method

通过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 ()

Field

和Method类似,把 getMethod 函数换成了 getField

接口说明:

// 属性名 --> 获取 Class 对象中指定属性名的属性( 不包含从父类继承的属性 )
public Method getDeclaredField (String name)

// 获取该 Class 对象中的所有属性( 不包含从父类继承的属性 )
public Method[] getDeclaredFields ()

// 属性名 --> 获取指定的 Class 对象中的**公有**属性,( 包含从父类和接口类集成下来的公有属性 )
public Method getField (String name)

// 获取该 Class 对象中的所有**公有**属性 ( 包含从父类和接口类集成下来的公有属性 )
public Method[] getFields ()

Other

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;
    }

}

你可能感兴趣的:(java,反射)