欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 社会 > Java反射机制(细节生动版)

Java反射机制(细节生动版)

2025/4/2 10:46:19 来源:https://blog.csdn.net/2301_81776550/article/details/146541584  浏览:    关键词:Java反射机制(细节生动版)

系列文章目录

Java反射机制


文章目录

  • 系列文章目录
  • 前言
  • 一、反射的定义:
  • 二、反射的相关类:
    • 反射的核心API
  • 三、Java程序计算机三个阶段
    • 1.new对象创建流程分析:
    • 2.反射创建对象:
    • 3.类比:
  • 四、Class类的details:
  • 五、获取Class类对象:
  • 六、反射的典型操作和爆破:
  • 总结


前言

   前期我们如果想得到一个对象是通过new的方式来创建对象的,但实际上在Java底层会进行类加载生成一个唯一类对象,里面存放着该类的信息,我们也可以通过这个对象来创建出来实例,Java 是静态类型语言,编译时需明确知道所有类型信息。但某些场景(如框架、插件系统)需要在运行时动态加载和操作未知类。反射允许在运行时分析类结构、创建对象、调用方法,无需在编译时硬编码类型。因此我们引入了反射,下面我们给大家具体讲一下:


  Java反射机制样例:

    通过外部文件配置,在不修改源码的情况下,来控制程序,也符合设计模式的OCP原则(开闭原则:不修改原码,扩容功能)

一、反射的定义:

       1.反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法,反射在设计模式和框架底层都会用到。

        2.加载完类之后,在堆中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息,通过这个对象得到类的结构,这个对象就像一面镜子,透过这个镜子看到类的结构,所有形象的称之为:反射

         核心能力:突破静态代码的限制,实现 ​动态加载类、修改行为、调用私有 API 等高级操作。

二、反射的相关类:

反射的核心 API

类/接口作用
Class<T>表示类的元信息(如 String.classobj.getClass())。
Field获取或修改字段的值(包括私有字段)。
Method动态调用方法(method.invoke(obj, args))。
Constructor<T>创建对象实例(支持有参/无参构造器)。
Modifier解析修饰符(如 publicstatic)。

     反射的相关类:

  1.  Java.lang.class 代表一个类,class对象表示某个类加载后在堆中的对象。

  2. Java.lang.reflect.Method 代表类的方法,Method对象表示某个类的方法。

  3.Java.lang.reflect.Field 代表类的成员变量,Filed对象表示某个类的成员变量。

  4. Java.lang.reflect.Consructor 代表类的构造方法,Consructor对象表示构造器。

三、Java程序计算机三个阶段:

    这里面我们还是要了解一下这三个阶段的,因为跟反射有关。

      这里面我们需要注意的是new和反射机制在创建对象的时候是不一样的。

 new对象创建流程分析:

以Person类为例子:

    1.加载Person类信息(Person.class),只会加载一次。

    2.在堆中分配空间(地址)

    3. 完成对象初始化(1.默认初始化 age=0,name=null 2.显式初始化 3.构造器初始化)

    4.对象在堆中的地址返回给P(对象名或对象的引用)

details:

  1. 内存分配

    • JVM 根据方法区中 MyClass 的元数据(如字段数量和类型),计算对象需要的内存大小。
    • 在堆中分配内存,并初始化对象头(包括指向方法区中 MyClass 元数据的类型指针)。
  2. 字段初始化

    • 默认初始化:所有字段设为默认值(如 int 为 0,对象引用为 null)。
    • 显式初始化:通过构造函数(<init> 方法)为字段赋值。
  3. 关键点

    • 对象的创建完全依赖方法区中的元数据(字段布局、构造函数等)。
    • 对象头中的类型指针:确保对象知道自己属于哪个类(通过它找到方法区中的元数据)。

       反射创建对象:

  Class 对象本身不包含成员变量、方法的实现或构造器的代码,它只是提供反射接口去访问方法区中的元数据。

    类比:

  • 方法区(元数据)​:像一本“蓝图手册”,记录了类的结构(字段、方法、构造器等信息)。
  • Class 对象:像这本手册的“目录索引”,告诉你如何快速找到需要的字段或方法。
  • 对象实例:按照蓝图手册建造出来的“房子”,每个房子知道自己对应的蓝图(通过对象头中的类型指针)。

  四、Class类的details:   

      1.Class也是类,因此是继承Object类。

      2.Class类不是new出来的,而是系统创建的。

      3.对于某个类的Class类对象,在内存中只有一份,因此类只加载一次。

      4.每个类的实例都会记得自己是由哪个Class实例所生成。

      5.通过Class对象可以完整地得到一个类的完整结构,通过一系列API。

      6.Class对象是放在堆中的。

      7.类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括方法代码,变量名,方法名和访问权限等等。)

     五、获取Class类对象:

   1.已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法来调用:

      

Class cls1 = Class.forname("类的具体路径");

     场景:多用于配置文件,读取类全路径,加载类。

   2.已知具体的类,通过类的Class获取,该方式最为安全可靠,程序性能最高。

     

Class cls2 = 类名.class;

    场景:多用于参数传递,比如通过反射来获得对应的构造器对象。

   3.对象.getClass();

     场景:有对象实例。

   4.通过类加载器来获取到类的Class对象:

       (1)先得到类加载器Car:

ClassLoader classLoader = car.getClass().getClassLoader();

         (2) 通过类加载器得到class对象:

Class cls4 = classLoader.loaderClass("classAllPath");

     5. 基本数据类型:

Class<Integer> integerClass = int.class;

    6.包装类:

Class<Integer> type = Integer.TYPE;

这里面我们还需要知道的一点就是为什么会有反射机制呢,我们要了解静态加载和动态加载:

   反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载:

静态加载:编译时加载相关的类,如果没有则报错。

动态加载:运行时加载需要的类,如果运行时不用该类,则不报错,降低了依赖性。

六、反射的典型操作和爆破:

        

Class<?> clazz = User.class;
User user = (User) clazz.getDeclaredConstructor().newInstance();// 获取构造器(参数类型需匹配)
Constructor<User> constructor = clazz.getDeclaredConstructor(String.class, int.class);
User user = constructor.newInstance("Alice", 30);// 获取所有 public 字段(包括父类)
Field[] publicFields = clazz.getFields();// 获取本类所有字段(包括私有)
Field[] allFields = clazz.getDeclaredFields();// 获取指定字段(需处理 NoSuchFieldException)
Field nameField = clazz.getDeclaredField("name");// 设置可访问性(针对私有字段)
nameField.setAccessible(true);// 读取字段值
String nameValue = (String) nameField.get(user);// 修改字段值
nameField.set(user, "Bob");// 获取所有 public 方法(包括父类)
Method[] publicMethods = clazz.getMethods();// 获取本类所有方法(包括私有)
Method[] allMethods = clazz.getDeclaredMethods();// 获取指定方法(需参数类型匹配)
Method setNameMethod = clazz.getDeclaredMethod("setName", String.class);// 设置可访问性(针对私有方法)
setNameMethod.setAccessible(true);// 调用实例方法(需传入对象实例)
setNameMethod.invoke(user, "Charlie");// 调用静态方法(对象实例传 null)
Method staticMethod = clazz.getDeclaredMethod("staticMethod");
staticMethod.invoke(null);

   爆破其实没什么神秘的,就相当于针对的是私有的修饰的属性或方法,相当于有一扇门我们要把它炸开,需要用setAccessible(true)方法。


总结

以上就是今天要讲的内容,本文帮助大家简单温习了一遍Java的反射机制,以及它的使用和类加载的内容,它的优点就是可以动态的创建和使用对象,使用灵活,没有反射机制,框架技术就失去了底层支撑。但是缺点就是解释执行,对执行速度有影响。

好了谢谢大家,接下来的两个星期我会开始进行大量算法题的更新,因为蓝桥杯快到了,我们一起进步,加油。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词