Java-反射

Java代码在计算机上的三阶段

  1. 源代码阶段。源代码经过编译,生成class文件
  2. Class类对象阶段。成员变量被封装为Field对象,构造函数被封装为Constructor对象,成员方法被封装为Method对象
  3. Runtime运行时阶段
  • 源代码阶段-->Class类对象阶段:ClassLoader将class字节码加载进内存
    • 加载时机:类第一次被使用(懒加载)

反射好处:

  1. 可以在程序的运行过程中,操作这些对象
  2. 可以解耦,提高程序的可拓展性

获取Class对象的方式

  1. Class.ForName("全类名"):将字节码文件加载进内存,返回Class对象
    • 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
  2. 类名.class:通过类名的属性class获取
  3. 对象.getClass():getClass()方法在Object类中定义着
  • 注意:同一个字节码文件(*.class)在一次程序的运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个

Class对象功能

获取功能

  1. 获取成员变量们
    • Field[] getFields():获取所有public修饰的成员变量
    • Filed getField(String name)
    • Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
    • Field getDeclaredField(String name)
  2. 获取构造方法们
    • Constructor<?>[] getConstructors()
    • Constructor getConstructor(类<?>... parameterTypes)// 参数举例:(String.class, int.class)
    • Constructor<?>[] getDeclaredConstructors()
    • Constructor getDeclaredConstructor(类<?>... parameterTypes)
  3. 获取成员方法们
    • Method[] getMethods()
    • Method getMethod(String name, 类<?>... parameterTypes)
    • Method[] getDeclaredMethods()
    • Method getDeclaredMethod(String name, 类<?>... parameterTypes)
  4. 获取类名
    • String getName()

Filed:成员变量

  • 操作:
    1. 设置值
      • void set(Object obj, Object value)
    2. 获取值
      • get(Object obj)
    3. 忽略访问权限修饰符的安全检查
      • setAccssible(true):暴力反射

Constructor:构造方法

  • 创建对象
    • T newInstance(Object... initargs)
    • 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

Method:方法对象

  • 执行方法:
    • Object invoke(Object obj, Object... args)
    • String getName():获取方法的名称

案例

  1. ReflectTest.java
package com.study;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class ReflectTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
	// write your code here

        /**
         * 案例:写一个“框架”,在不改变类的任何代码的情况下,可以帮助我们创建任意类的对象,并且执行其中任意的方法
         * 实现:1.配置文件:
         *          ClassName=com.study.refelct.Dog
         *          MethodName=sleep
         *      2.反射
         * 步骤:1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中
         *      2.在程序中加载读取配置文件
         *      3.使用反射技术来加载文件进内存
         *      4.创建对象
         *      5.执行方法
         */
        Properties properties = new Properties();
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        properties.load(classLoader.getResourceAsStream("pro.properties"));

        String className = properties.getProperty("ClassName");
        String methodName = properties.getProperty("MethodName");

        Class cls = Class.forName(className);
        Object obj = cls.newInstance();
        Method method = cls.getMethod(methodName);
        method.invoke(obj);

    }
}
  1. Dog.java
package com.study.refelct;

public class Dog {
    public void sleep(){
        System.out.println("dog sleep...");
    }
}

  1. pro.properties
ClassName=com.study.refelct.Dog
MethodName=sleep
posted @ 2022-04-17 22:10  Z_Y_L  阅读(20)  评论(0编辑  收藏  举报