Java反射机理简介

反射:框架设计的灵魂

  • 框架:半成品软件,可以在框架的基础上进行软件开发,简化代码
  • 反射:将类的各个组成部分封装为其他对象,这就是反射机制
    • 好处:
    1. 可以在程序运行过程中操作这些对象
    2. 可以解耦,提高程序的可扩展性

** Java代码在计算机中经历的三个阶段:
Source源代码阶段、Class类对象阶段、Runtime 运行时阶段
在这里插入图片描述

  • 获取Class对象的方式:

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

  • Class对象功能( 获取功能):

    1. 获取成员变量
      • Field[] getFields():获取所有public修饰的成员变量
      • Field getField(String name):获取指定名称的public修饰的成员变量
      • Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
      • Field getDeclaredField(String name):获取指定名称的成员变量
    2. 获取构造方法
      • Constructor<?>[] getConstructors()
      • Constructor getConstructor(类<?>…parameterTypes)
      • Constructor<?>[] getDeclaredConstructors()
      • Constructor getDeclaredConstructor(类<?>…parameterTypes)
    3. 获取成员方法
      • Method[] getMethods()
      • Method getmethod(String name,类<?>…parameterTypes)
      • Method[] getDeclaredMethods()
      • Method getDeclaredmethod(String name,类<?>…parameterTypes)
    4. 获取类名
      • String getName()
  • Field:成员变量

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

    • 创建对象:
    • T newInstance(Object… initargs)
    • 如果使用空参数构造方法创建对象,操作可以简化:
      Class对象的newInstance
  • Method:方法对象
    *执行方法:
    *Object invoke(Object obj, Object… args)

  • 获取方法名称:

  • String getName:获取方法名

  • 案例:

    • 需求:写一个“框架”,不能改变该类的任何代码的前提下,可以帮助我们 创建任意类的对象,并且执行其中任意方法
    • 实现:
    1. 配置文件
    2. 反射
    • 步骤:
    1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
    2. 在程序中加载读取配置文件
    3. 使用反射技术来加载类文件进入内存
    4. 创建对象
    5. 执行方法
  • 案例代码(获取Class对象功能):

  1. 创建一个类
package product;

public class Person {
    public String name = "张同学";
    public void eat(){
        System.out.println("Person eating...");
    }
}
  1. 创建一个可以获取Class对象功能的类
package product;

        import java.lang.reflect.Field;
        import java.lang.reflect.Method;

public class Class对象功能 {
    public static void main(String[] args) throws Exception {
        //获取Person的Class对象
        Class PersonClass = Person.class;
        Method[] b = PersonClass.getDeclaredMethods();
        for (Method e:b) {
            System.out.println(e);
        }
        //获取成员变量name的值
        Field c = PersonClass.getField("name");
        Person p = new Person();
        Object d = c.get(p);
        System.out.println(d);
    }
}

3.测试结果:
在这里插入图片描述

  • 案例代码(注意:配置文件必须与项目包在同一个级别下):
  1. 创建一个类用来测试
package product;
public class Person {
    public void eat(){
        System.out.println("Person eating...");
    }
}
  1. 创建一个配置文件(文件后缀名为.properties)
className = product.Person   //测试类的全类名
methodName = eat	//需要测试的方法

3.创建一个可以加载配置文件的类

package product;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

@SuppressWarnings("all")
public class reflectTest {
    public static void main(String[] args) throws Exception {
        //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 cls = Class.forName(className);
        //4创建对象
        Object obj = cls.newInstance();
        //5 获取方法对象
        Method method = cls.getMethod(methodName);
        //6 执行方法
        method.invoke(obj);
    }
}
  1. 测试结果:
    Person eating…
发布了5 篇原创文章 · 获赞 8 · 访问量 388

猜你喜欢

转载自blog.csdn.net/qq_40679438/article/details/105422593