Java反射

反射

概述

反射:将类的各个组成部分封装为其他对象,这就是反射机制

  • 可以在程序运行过程中,操作这些对象
  • 可以解耦,提高程序的可扩展性

image-20220408224958807获取Class对象的方式

  • Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象----->对应第一阶段源代码阶段
    • 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
  • 类名.class:通过类名的属性class获取---------->对应第二阶段 内存加载阶段
    • 多用于参数的传递
  • 对象.getClass():getClass()方法在Object类中定义着 ------->对应 第三阶段创建对象的运行阶段
    • 多用于对象的获取字节码的方式
//获取类对象的三种方式
        //1.Class.forName("全类名")
        Class aClass = Class.forName("com.z.Reflect");
        System.out.println(aClass);

        //2.类名.class:通过类名的属性class获取
        Class aClass1 = Reflect.class;
        System.out.println(aClass1);

        //3.对象.getClass()
        Reflect reflect = new Reflect();
        Class aClass2 = reflect.getClass();
        System.out.println(aClass2);

        System.out.println(aClass==aClass1);
        System.out.println(aClass==aClass2);

结论:
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

Class对象功能

1. 获取成员变量们 Field(成员变量)

// Field[] getFields() :获取所有public修饰的成员变量
Class personClass= Class.forName("com.z.Person");
Field[] fields = personClass.getFields();
for (Field field : fields) {
    System.out.println(field);
}
System.out.println("=============");

//Field getField(String name)   获取指定名称的 public修饰的成员变量
Field field_a = personClass.getField("a");//获取成员变量a
System.out.println(field_a);

Person p = new Person();
Object value = field_a.get(p);//获取成员变量a的值
System.out.println(value);
field_a.set(p,"QQQ");//设置成员变量a的值
System.out.println(p);

System.out.println("=============");

//Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
    System.out.println(declaredField);
}
System.out.println("=============");

//Field getDeclaredField(String name)
Field d = personClass.getDeclaredField("d");//d为私有成员变量
System.out.println(d );
//忽略访问权限修饰符的安全检查---->获取和设置私有成员变量的值
d.setAccessible(true);//暴力反射
Object value2 = d.get(p);
System.out.println(value2);
d.set(p,"WWW");
System.out.println(p);
System.out.println("=============");

另附Person类

package com.z;


public class Person {
    private String name;
    private int age;

    public String a;
    protected String b;
    String c;
    private String d;


    public Person(String name, int age, String a, String b, String c, String d) {
        this.name = name;
        this.age = age;
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    public Person() {

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    public String getC() {
        return c;
    }

    public void setC(String c) {
        this.c = c;
    }

    public String getD() {
        return d;
    }

    public void setD(String d) {
        this.d = d;
    }


    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }

    public void eat(){
        System.out.println("吃午饭!");
    }
    public void eat(String food){
        System.out.println("吃午饭!食物是:"+food);
    }
}

2. 获取构造方法们

//Constructor<?>[] getConstructors()
      //有参构造器
      Constructor constructor = personClass.getConstructor(String.class, int.class);
      System.out.println(constructor);
      //获取构造器之后可以创建对象
      Object person = constructor.newInstance("张三", 18);//创建person对象
      System.out.println(person);

      //无参构造器
      Constructor constructor1 = personClass.getConstructor();
      Object person1 = constructor1.newInstance();
      System.out.println(person1);
      //简化无参生成对象
      Object o = personClass.newInstance();
      System.out.println(o);

      //Constructor<T> getConstructor(类<?>... parameterTypes)

      //Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
      //Constructor<?>[] getDeclaredConstructors()

3. 获取成员方法们

//Method[] getMethods()
//Method getMethod(String name, 类<?>... parameterTypes)
Method[] methods = personClass.getMethods();
for (Method method : methods) {
    System.out.println(method);
}

//无参方法
Method eat_method = personClass.getMethod("eat");//获取eat方法
//拿到方法--->执行
eat_method.invoke(o);

//有参方法
Method eat_method2 = personClass.getMethod("eat", String.class);
eat_method2.invoke(o,"米饭");
//Method[] getDeclaredMethods()
//Method getDeclaredMethod(String name, 类<?>... parameterTypes)

4.获取全类名

//String getName()
String personClassName = personClass.getName();
System.out.println(personClassName);

反射案例

实现一个框架类–>可以创建任意对象,执行任意方法(不能改变该类的任何代码)

新建一个pro.properties资源文件

className=com.z.Student
methodName=sleep

框架类

package com.z;

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

/**
 * 框架类-->可以创建任意对象,执行任意方法(不能改变该类的任何代码)
 *
 * 实现技术:配置文件、反射
 *
 * 步骤:
 *1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
 *2. 在程序中加载读取配置文件
 *3. 使用反射技术来加载类文件进内存
 *4. 创建对象
 *5. 执行方法
 *
 */
public class ReflectProject {
    public static void main(String[] args) throws Exception{

        //1.加载配置文件
        //1.1创建properties对象
        Properties properties = new Properties();//创建配置对象
        //1.2加载配置文件,转换为一个集合
        //1.2.1获取class目录下的配置文件
        ClassLoader classLoader = ReflectProject.class.getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream("com/pro.properties");
        properties.load(inputStream);



        /**
        ClassLoader的作用:基本上所有的类加载器都是 java.lang.ClassLoader类的一个实例。
        它是用来加载 Class 的。它负责将 Class 的字节码形式转换成内存形式的 Class 对象。
        除此之外,ClassLoader还负责加载 Java 应用所需的资源,如图像文件和配置文件等
        */

        //2.获取配置文件中定义的数据
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");

        //加载该类进内存
        Class cls = Class.forName(className);

        //创建对象
        Object o = cls.newInstance();
        System.out.println(o);
        //获取方法对象
        Method method = cls.getMethod(methodName);
        //执行方法
        method.invoke(o);


    }
}

通过修改配置文件可以实现生成任意类的对象,并执行指定的方法

image-20220413201708887

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值