Java反射笔记(自用)

8 篇文章 0 订阅
6 篇文章 0 订阅

一.java程序编译运行过程

java源代码 - - - 编译器 - - - jvm可执行的字节码 - - - jvm中的解释器 - - - 机器可执行的二进制机器码 - - - 程序运行

1. Java源代码

  • 编写:开发者使用Java语言编写源代码,保存在以.java为扩展名的文件中。

2. 编译器

  • 编译:Java编译器(如javac)将.java文件中的源代码编译成Java字节码。这一步涉及语法分析、语义检查、生成中间表示和最后生成字节码。
  • 输出:编译器生成的输出是.class文件,其中包含与源代码对应的字节码。

3. JVM可执行的字节码

  • 字节码:字节码是一种介于源代码和机器码之间的中间形式,设计为可以在任何实现了Java虚拟机的平台上运行。

4. JVM中的解释器

  • 加载:当运行Java程序时,JVM的类加载器负责将.class文件加载到内存中。
  • 连接:在连接阶段,JVM执行验证、准备和解析步骤,确保代码的安全性和正确性。
  • 初始化:在此阶段,JVM处理静态变量和静态块,执行类构造器。

5. 机器可执行的二进制机器码

  • 解释执行:JVM的解释器逐条解释执行字节码,将其翻译成可以在特定硬件上执行的机器指令。这是一个逐步的过程,每次解释一条字节码指令。
  • 即时编译(JIT编译):为了提高性能,热点代码(即执行次数较多的代码)会被JVM中的即时编译器编译成本地机器码,这样可以直接由硬件执行,无需再进行逐条解释,从而提高执行效率。

6. 程序运行

  • 执行:经过上述所有转换和处理后,程序最终在计算机硬件上运行,用户可以看到程序执行结果。

二.什么是反射

官方定义: 反射(Reflection)是一个强大的机制,它允许程序在运行时查询和操作对象的类信息。使用反射API,可以动态地创建对象、调用方法、访问字段(即便它们被定义为私有的),并且能够加载类。

1.反射与字节码的关系

字节码是java源代码经过javac编译器编译后的中间文件表现形式,即.class里面的内容,这些字节码可以当作jvm的执行的指令集。
而反射是一种在运行时检查或修改程序行为的机制。它以字节码为基础,就是它会首先创建一个Class对象,这个对象能够从字节码中读取类信息,即构造函数,方法,字段这些,私有的也可以访问到,所以具有动态操作的优点和破坏封装性的缺点.

2.Class对象工作流程

  1. 类加载:JVM首次引用某个类时,它将加载该类的字节码,解析字节码中的元数据,并为这个类创建一个Class类型的对象。

  2. 信息访问:通过这个Class对象,可以访问类的各种信息:

    • 获取字段(Field):可以检索类中声明的所有字段,无论它们的访问权限如何。
    • 获取方法(Method):可以获取类定义的所有方法。
    • 获取构造器(Constructor):可以访问类的所有构造方法。
    • 获取超类和接口:可以查看类的父类和实现的接口。
  3. 创建实例:可以使用Class对象来创建其表示的类的实例。这通常通过调用newInstance()方法实现,或者通过获取适当的构造器对象并调用其newInstance()方法。

  4. 动态操作:可以动态调用方法或访问字段,这在编译时是未知的,所以不需要指定特殊类。

三.反射的使用

1. 获取Class对象

Class<?> clazz1 = Class.forName("java.util.ArrayList"); // 通过类的全限定名

Class<?> clazz2 = ArrayList.class; // 通过类字面量

ArrayList<String> arrayList = new ArrayList<>();
Class<?> clazz3 = arrayList.getClass(); // 通过对象实例调用getClass()

2. 创建对象实例

Class<?> clazz = Class.forName("java.util.ArrayList");
Object arrayList = clazz.getDeclaredConstructor().newInstance(); // 创建对象实例

3. 访问字段

Class<?> clazz = Class.forName("com.example.MyClass");
Field field = clazz.getDeclaredField("myField"); // 获取指定字段
field.setAccessible(true); // 设置可访问性,对于私有字段非常重要
Object fieldValue = field.get(instance); // 读取字段值
field.set(instance, "new value"); // 设置新的字段值

4. 调用方法

Class<?> clazz = Class.forName("com.example.MyClass");
Method method = clazz.getDeclaredMethod("myMethod", String.class); // 获取方法
method.setAccessible(true); // 对于私有方法必须这么做
Object result = method.invoke(instance, "parameter"); // 调用方法

5. 操作数组

int[] intArray = (int[]) Array.newInstance(int.class, 3); // 创建一个整型数组
Array.set(intArray, 0, 123); // 设置数组元素
int value = Array.getInt(intArray, 0); // 获取数组元素
  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值