反射之基础

本文深入探讨了Java中的反射机制,它是框架设计的核心。反射允许在运行时检查和操作类的属性、构造器和方法。通过Class对象,可以获取类的详细信息,并进行动态对象创建和方法调用。文中提供了详细的代码示例,展示了如何通过反射获取和修改成员变量、构造对象以及调用方法。此外,还给出了一个实际案例,说明如何利用反射从配置文件中创建并执行任意类的方法,强调了反射在解耦和提高程序可扩展性方面的价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射

反射:框架设计的灵魂

  • 框架:半成品软件。可以在框架的基础上进行软件开发,简化代码。

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

  • Java代码在计算机中经历的三个阶段

    用处:

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

在这里插入图片描述

1,获取Class对象的方法

  • 1,(为加载字节码文件进内存,即,还未生成对应的Class对象)Class.forName("全类名"):(即包括路径)将字节码文件加载进内存并返回Class对象;
    • 多数用于配置文件,将类名定义在配置文件中
  • 2,(已有对应的Class对象,例如已经定了一个对应的指针,此时会自动加载字节码文件)使用类名获取 类名.class
    • 多用于参数传递
  • 3,(已有对象了)使用getClass()方法,该方法在Object类中有定义对象.getClass()
    • 用对象获取字节码对象

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

2,Class对象的功能

2.1 获取功能

  • 1,获取成员变量们

    • Field[] getFields():获取public修饰
    • Field getField(String name):获取指定名称public修饰的成员变量
    • Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
    • Field getDeclaredField()
  • 2,获取构造方法们

    • Constructor<?>[] getConstructors()
    • Constructor<T> getConstructor(类<?>... parameterTypes)
    • Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
    • Constructor<?>[] getDeclaredConstructors()
  • 3,获取成员方法们

    • Method[] getMethods()
    • Method getMethod(String name, 类<?>... parameterTypes)
    • Method[] getDeclaredMethods()
    • Method getDeclaredMethod(String name, 类<?>... parameterTypes)
  • 4,获取类名

    • String getName()

2.2 Field

可用操作

  • 1)设置值:
    • void set(Object obj,Object value)
  • 2)获取值:
    • Object get(Object obj)
  • ``3)忽略访问权限修饰符的安全检查
    • setAccessible(true):暴力反射:使得变量可以被访问
class person{
    public String a;
    private String b;
}

Class personClass=Person.class;
Field a= personClass.getField("a");
Person p=new Person();
//获取成员变量a的值
Object value = a.get(p);
//设置a的值
a.set(p,"张三");

Field b=personClass.getDeclaredField("b");
b.setAccessible(true);//暴力反射,使得b可以被访问
Object value=b.get(p);
System.out.println(value);//此时可以被访问

2.3 Constructor

  • 获取构造方法(以参数进行区分):getConstructor(类名1.class,类名2.class,...);

  • 创建对象:constructor1.newInstance();

class Person{
    String a;
    int age;
    public Person(){}
    public Person(String a,int age){
        this.a = a;
        this.age = age;
    }
}

Class personClass = Person.class;
Constructor constructor2 = personClass.getConstructor(String.class,int.class);
//创建对象
Object newPerson = constructor.newInstance("张三",23);
//空参构造:可简化
Object newPerson2 = personClass.newInstance();

2.4 Method

  • 获取成员方法

    • person.getMethod(类名1.class,类名2.class,...)
  • 调用成员方法

    • eat_Method2.invoke(p,"饭");
  • 获取成员方法名

    • method.getName()
class Person{
    String a;
    int age;
    public Person(){}
    public Person(String a,int age){
        this.a = a;
        this.age = age;
    }
    public void eat(){};
    pbulic void eat(String food){};
}
Person p = new Person();
Class personClass = Person.class; 

Method eat_Method1 = personClass.getMethod("eat");
eat_Method1.invoke(p);

Method eat_Method2 = personClass.getMethod("eat",String.class);
eat_Method2.invoke(p,"饭");
//获取所有的public修饰的方法
Method[] methods = PersonClass.getMethods();
for(Method method:methods){
    System.out.println(method);
    System.out.println(method.getName())
}

3,反射案例

1,需求

  • 写一个”框架“,可以帮助我们创建任意类的对象,并执行其中任意方法;
    • 实现:
      • 1,配置文件
      • 2,反射
    • 步骤:
      • 1,将需要创建的对象的全类名和需要执行的方法定义在配置文件中
      • 2,,读取配置文件
      • 3,利用反射加载类的字节码文件进内存
      • 4,创建对象
      • 5,执行方法

2,案例实现

本质是已经定义好了这个类,

2.1 配置文件
className = cn.day08.Person
methodName = eat
2.2 程序
public class ReflectTest{
    public static void main throws Exception(String[] args){
    //1,加载配置文件
        //1.1,创建Properties对象
		Properties pro = new Properties();
        //1.2加载配置文件
            //1.2.1 获取当前类的类加载器
        ClassLoader classLoader ReflectTest.class.getClassLoader();
        	//可以找到该src路径下的配置文件,直接获取对应资源的字节流
        InputStream is = classLoader.getResourseAsStream("pro.properties");
        pro.loa d(is);
        
    //2,获取配置文件中的对应数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");
           
    //3,加载该类进内存
        	//利用名字查找Class对象
        Class cls= Class.forName(className);
    //4,创建对象
        Object obj = cls.newInstance();
    //5,获取方法对象
        Method method = cls.getMethod(methodName);
        method.invoke(obj);
    }
}
s对象
        Class cls= Class.forName(className);
    //4,创建对象
        Object obj = cls.newInstance();
    //5,获取方法对象
        Method method = cls.getMethod(methodName);
        method.invoke(obj);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值