当前位置: 首页 > news >正文

Java反射基础

目录

  • 前言
  • 1. 字节码与类加载机制
        • 字节码
        • 类加载机制
  • 2. 获取 Class 对象的三种方式
        • 方式一:Class.forName("全类名")
        • 方式二:类名.class
        • 方式三:对象.getClass()
  • 3. 获取 Class 信息
        • 获取构造方法
        • 获取字段
        • 获取方法
  • 总结

前言

通过本篇文章,你将了解到 Java 反射的基本概念、为什么需要反射,以及如何获取 Class 对象并进行基础操作。


1. 字节码与类加载机制

在学习反射之前,我们先来简单了解一下字节码文件与 JVM 中的类加载机制。

字节码

我们编写的 Java 源代码保存在.java文件中。当我们在 IDE 中编译或运行代码时,编译器会将这些源文件编译成 JVM 可执行的字节码文件,其后缀为.class

类加载机制

从编写代码到程序运行,主要经历两个时期:编译期运行期

  • 编译期:程序员编写的.java代码被编译成.class字节码文件的阶段。
  • 运行期:JVM 找到并加载.class文件,将其数据读入内存中,并在堆区生成一个对应的Class对象。这个阶段被称为类加载

这个Class对象存储了该类的结构信息(如类名、父类、实现的接口、构造方法、属性和普通方法等)。

反射的核心,就是通过获取这个Class对象,来读取和操作该类的信息。


2. 获取 Class 对象的三种方式

理解了反射需要依赖Class对象后,我们来看一下在 Java 中获取Class对象的三种常用方式:

方式一:Class.forName(“全类名”)

全类名的意思是:package名+这个类的名字

假设有如下类:

packagecom.example;publicclassUser{// 省略属性与方法...}

那么该类的全类名为"com.example.User"

获取其Class对象的完整写法:

Class<?>clazz=Class.forName("com.example.User");

关于Class<?>:其含义是某种具体的类型的class对象。

  • ?是通配符,表示某种未知的具体类型。
  • 通过名字去查找,编译器无法确定该类具体是什么类型,所以使用Class<?>
  • 可以通过强制类型转换实现:
    Class<User>clazz=(Class<User>)Class.forName("com.example.User");
  • 由于是通过字符串名称查找,找不到的话,会抛出已检查异常ClassNotFoundException
方式二:类名.class

如果我们已经在写代码的时候,明确知道要操作哪个类。

Class<User>clazz=User.class;

在编译期进行类型检查,如果类名写错,编译器会直接报错,不需要处理ClassNotFoundException异常。

方式三:对象.getClass()

已经拥有了某个类的对象实例时,通过该实例获取其对应的Class对象:

Userbean=newUser();Class<?extendsUser>clazz=bean.getClass();

如果对象实例为null,会抛出空指针异常NullPointerException


3. 获取 Class 信息

获取到Class对象后,可以获取类的构造方法、字段以及普通方法。

获取构造方法

获取指定的被public修饰的构造方法。
clazz.getConstructor(Class<?>... parameterTypes)

获取指定的任意修饰符(包括private)的构造方法。clazz.getDeclaredConstructor(Class<?>... parameterTypes)

假设User类:

publicclassUser{privateStringname;privateIntegerage;// 构造方法一:无参构造publicUser(){}// 构造方法二:单参构造(String)publicUser(Stringname){this.name=name;}// 构造方法三:多参构造publicUser(Stringname,Integerage){this.name=name;this.age=age;}// 构造方法四:私有单参构造(int)privateUser(intage){this.age=age;}}

获取对应的构造器:

Class<User>clazz=User.class;// 获取无参构造方法Constructor<User>c1=clazz.getDeclaredConstructor();// 获取单参构造方法(String)Constructor<User>c2=clazz.getDeclaredConstructor(String.class);// 获取多参构造方法(String, Integer)Constructor<User>c3=clazz.getDeclaredConstructor(String.class,Integer.class);// 获取私有构造方法(int)Constructor<User>c4=clazz.getDeclaredConstructor(int.class);

利用获取到的构造方法创建对象

c4.setAccessible(true);Userbean=c4.newInstance(18);

private构造方法、字段或方法,在操作前必须调用setAccessible(true)

默认情况下,访问权限检查为false,强行访问私有成员会抛出IllegalAccessException

获取字段

获取指定的单个属性(无论何种修饰符)
clazz.getDeclaredField(String name)

获取类中声明的所有属性。
clazz.getDeclaredFields()

// 获取名为 "name" 的私有字段Fieldfield=clazz.getDeclaredField("name");// 解除私有访问限制field.setAccessible(true);// 为指定对象的该属性赋值field.set(bean,"张三");// 获取指定对象的该属性值Stringname=(String)field.get(bean);

关于field.set(bean, "张三");
写bean的原因是,写明给哪一个实例化的对象的字段赋值

获取方法

获取指定的成员方法。需要传入方法名, 参数类型的 Class
clazz.getDeclaredMethod(String name, Class<?>... parameterTypes)

调用该方法。传入要执行的对象实例和具体的参数值。
method.invoke(Object obj, Object... args)

// 获取 setName(String) 方法Methodmethod=clazz.getDeclaredMethod("setName",String.class);// 执行方法method.invoke(bean,"李四");// 如果是静态方法,调用时对象实例传 null 即可// staticMethod.invoke(null, args);

总结

  1. 反射的核心是 Class 对象:它是.class字节码文件被 JVM 加载到内存后生成的类型元数据表示。
  2. 获取 Class 对象的三种方式
    • Class.forName("全类名")适用于动态配置文件加载;
    • 类名.class最为安全,适用于编译期已确定类型的场景;
    • 对象.getClass()适用于已知对象实例的场景。
  3. 反射可打破封装限制:通过调用setAccessible(true),反射可以访问和操作包括private在内的私有构造方法、字段和方法。
  4. 反射是框架设计的基石:虽然反射增加了运行时的灵活性(如 Spring IoC、MyBatis 映射),但过度使用反射会带来性能开销,并且破坏了面向对象的封装性。
http://www.jsqmd.com/news/1106134/

相关文章:

  • Frida内存操作避坑指南:从原理到实战的逆向分析核心技能
  • CNN-LSTM-AdaBoost时间序列预测实战指南
  • 大模型推理加速年度趋势:从量化到稀疏化的技术跃迁路径
  • ActiveReports for .NET 20.0J SP1-AIレポートウィザードがさらに進化
  • 大模型推理加速核心:KV Cache 复用机制与内存布局优化
  • 开启 OpenFeign 调用日志打印
  • Nuke Survival Toolkit:150个Nuke插件的终极指南与完整解决方案
  • CAD二次开发中的公差控制
  • Electron + Rust:吉他谱播放器性能优化实战
  • 抖音音频下载终极指南:5分钟掌握免费开源工具
  • 无限集(深圳)8年汽车电子深耕,12+整车厂定点
  • c++复习自存
  • 记录一个标记所有new出来的内存的地址加上TAG
  • AI 辅助:Product Hunt 发布复盘:上线当天之前,准备已经开始
  • Cursor Free VIP破解工具:3分钟解除AI编程助手试用限制的终极指南
  • 西安共享茶室平台开发?时段预约锁房技术源码讲解
  • 封装统一多模态客户端(整合文字对话 + 文生图 + 语音转写)
  • 利用金字塔原理学习PHP的具象化的庖丁解牛
  • 汽车电子散热管理:DRV8213驱动器与MF25060V2风扇实战
  • 【小白也能轻松玩转龙虾】虾壳云一键部署入门攻略,分步搭建桌面端 OpenClaw v2.7.9(附最新安装包)
  • React 渲染性能:组件边界、状态下沉与重渲染治理
  • 后端开发者转型AI大模型的必备技能与实战指南
  • AI 辅助:独立开发者技术选型:最好的技术是能让产品活下去
  • AI 辅助:少说漂亮话:基础设施要用事故假设来设计
  • AI 辅助:独立创作:工具应放大作者,而不是替代作者
  • 一文看懂 DDoS 与 CC 攻击:攻击类型全解析 + 完整防护方案
  • 5个场景化解决方案:用taskt告别重复劳动,实现桌面自动化革命
  • Harness Engineering(驾驭工程)简单的演化过程
  • 阿贝云免费云服务器磁盘空间合理分配实操心得
  • 2025了会议纪要还写得慢又漏任务?听脑帮你智能提取任务超省心!