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 {

    /**
     * 循环向上转型, 获取对象的 DeclaredMethod
     *
     * @param object         : 子类对象
     * @param methodName     : 父类中的方法名
     * @param parameterTypes : 父类中的方法参数类型
     * @return 父类中的方法对象
     */

    public static Method getDeclaredMethod(Object object, String methodName, Class<?>... parameterTypes) {
        Method method;

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

    /**
     * 循环向上转型, 获取对象的 DeclaredField
     *
     * @param object : 子类对象
     * @param fieldName : 父类中的属性名
     * @return 父类中的属性对象
     */

    public static Field getDeclaredField(Object object, String fieldName) {
        Field field;

        for (Class<?> clazz = object.getClass(); clazz != Object.class;
            clazz = clazz.getSuperclass()) {
            try {
                field = clazz.getDeclaredField(fieldName);
                return field;
            } catch (Exception e) {
                //这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。
                //如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了
            }
        }

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

        try {
            if (null != method) {
                //抑制Java对方法进行检查,主要是针对私有方法而言
                method.setAccessible(true);
                //调用object 的 method 所代表的方法,其方法的参数是 parameters
                return method.invoke(object, parameters);
            }
        } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

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

        try {
           if (null != field) {
               //抑制Java对其的检查
               field.setAccessible(true);
               //将 object 中 field 所代表的值 设置为 value
               field.set(object, value);
           }
        } catch (IllegalArgumentException | 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);

        try {
           if (null != field) {
               //抑制Java对其的检查
               field.setAccessible(true);
               //获取 object 中 field 所代表的属性值
               return field.get(object);
           }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值