JAVA反射相关的类及其方法

1,238 阅读3分钟

程序经过javac.exe命令执行后,会生成一个或多个字节码文件(.class文件),再使用java.exe命令对某个字节码文件进行解释运行。相当于将该字节码文件加载到内存中,此过程就称为类的加载。加载到内存中的类,称为运行时类,此运行时类,就作为Class类的一个实例。

一、获取Class类对象的方法

  • Class.forName("全类名")
    Class cls1 = Class.forName("JW.yx.domain.Person");
  • 类名.class
    Class cls2 = Person.class;
  • 对象.getClass()
    Person person = new Person();
    Class cls3 = person.getClass();

二、使用Class对象获取成员变量

  • Field[] getFields():获取所有public修饰的成员变量
    Class<Person> personClass = Person.class;
    Field[] fields = personClass.getFields();
  • Field getField(String name):获取指定名称的public修饰的成员变量
    Class<Person> personClass = Person.class;
    Field name = personClass.getField("name");
  • Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
    Class<Person> personClass = Person.class;
    Field[] declaredFields = personClass.getDeclaredFields();
  • Field getDeclaredField(String name):获取指定的成员变量,不考虑修饰符
    Class<Person> personClass = Person.class;
    Field sex = personClass.getDeclaredField("sex");

三、设置和获取成员变量的值

  • void set(Object obj, Object value):设置
    Class<Person> personClass = Person.class;
    Field name = personClass.getField("name");
    Person p = new Person();
    name.set(p,"掘金")
  • get(Object obj):获取
    Class<Person> personClass = Person.class;
    Field name = personClass.getField("name");
    Person p = new Person();
    Object value = name.get(p);
  • setAccessible(true):暴力反射,如果获取到的成员变量的修饰符不是public,使用该方法对成员变量的值进行设置和获取
    Class<Person> personClass = Person.class;
    Field sex = personClass.getDeclaredField("sex");
    sex.setAccessible(true);
    sex.set(p,"男");
    Object value1 = sex.get(p);

三、使用Class对象获取构造方法

  • Constructor<?>[] getConstructors():获取所有public修饰的构造方法
    Class<Person> personClass = Person.class;
    Constructor[] constructors = personClass.getConstructors();
  • Constructor getConstructor(类<?>... parameterTypes):获取与参数类型匹配的public修饰的构造方法
    Class<Person> personClass = Person.class;
    Constructor constructor = personClass.getConstructor(String.class, int.class, String.class, int.class);
  • Constructor<?>[] getDeclaredConstructors():获取所有构造方法,不考虑修饰符
  • Constructor getDeclaredConstructor(类<?>... parameterTypes):获取与参数类型匹配的所有构造方法,不考虑修饰符

四、使用Class对象获取的构造方法创建对象

  • T newInstance(Object... initargs)
    Class<Person> personClass = Person.class;
    Constructor constructor = personClass.getConstructor(String.class, int.class, String.class, int.class);
    Object person = constructor.newInstance("掘金", 1, "男", 6);
  • 使用空参数构造方法创建对象,直接使用Class对象的newInstance方法
    Class<Person> personClass = Person.class;
    Person person2 = personClass.newInstance();

五、使用Class对象获取成员方法

  • Method[] getMethods():获取所有的public修饰的成员方法
    Class<Person> personClass = Person.class;
    Method[] methods = personClass.getMethods();
  • Method getMethod(String name, 类<?>... parameterTypes):获取与参数类型匹配的public修饰的成员方法
    Class<Person> personClass = Person.class;
    Method eat = personClass.getMethod("eat", String.class);
  • Method[] getDeclaredMethods():获取所有的成员方法,不考虑修饰符
  • Method getDeclaredMethod(String name, 类<?>... parameterTypes):获取与参数类型匹配的成员方法,不考虑修饰符

六、执行使用Class对象获取到的成员方法

  • Object invoke(Object obj, Object... args)
    Class<Person> personClass = Person.class;
    Method eat = personClass.getMethod("eat", String.class);
    eat.invoke(p,"苹果");
  • String getName:获取方法名
    eat.getName();
  • String getName:获取类名
    personClass.getName();

七、应用

    //1.加载配置文件
    //1.1创建Properties对象
    Properties pro = new Properties();
    //1.2加载配置文件,转换为一个集合
    //1.2.1获取class目录下的配置文件
    ClassLoader classLoader = ReflectTest.class.getClassLoader();
    InputStream is =classLoader.getResourceAsStream("pro.properties");
    pro.load(is);
    //2.获取配置文件中定义的数据
    String className = pro.getProperty("className");
    String methodName = pro.getProperty("methodName");
    //3.加载该类进内存
    Class c = Class.forName(className);
    //4.创建对象
    //4.1.获取构造方法创建对象
    Constructor constructor =c.getConstructor(String.class,int.class,String.class,int.class);
    Object p1 = constructor.newInstance("掘金", 1, "男", 6);
    //4.2.Class对象直接创建对象
    Object p = c.newInstance();
    //5.获取方法对象
    Method method = c.getMethod(methodName);
    //6.执行方法
    method.invoke(p);

只需修改pro.properties配置文件中的className、methodName值,即可创建对应的对象和执行对应的方法,体现了反射机制的动态性,反射是框架实现的灵魂。