java基础学习:java中的反射
作者:互联网
一、什么是java反射
什么是 java 的反射?
说到反射,写这篇文章时,我突然想到了人的”反省“,反省是什么?吾一日三省吾身,一般就是反思自身,今天做了哪些对或错的事情。
java 的反射,我觉得有同样的思想。当然 java 反射要“反思”的是 java 程序在运行时类自己的信息,它获取的信息就是它自身类的详细信息。
类的哪些详细信息呢?比如类或对象的成员变量、方法等。然后可以对这些信息加以修改,从而调整 java 的运行逻辑。
java 反射 API 提供了非常丰富的工具集,反射 API 能够获取对象的变量,方法等成员,从而可以动态的操纵 java 代码程序。文章后面会介绍这些反射 API(反射相关的类)的一些用法。
为什么反射能得到 java 程序运行时类的信息呢?这就要从 java 的虚拟机 jvm 说起。
二、虚拟机jvm加载文件
Java虚拟机(Java Virtual Machine):用于执行编译后的 java 程序的虚拟容器。jvm 可以跨操作系统使用。
jvm 内部结构分为 3 部分:类加载器classload子系统、运行时数据区、执行引擎。
以 .java
结尾的文件是不能直接在 jvm 上运行,它必须通过 javac 编译为以 .class
为后缀结尾的字节码文件才能运行。
java 文件被编译为 .class 的文件后,java 文件中各种对象的信息就确定下来了,存在于 .class 文件里。通过 java 的反射就可以获取里面的信息。
三、反射原理简析
在上一小节简单了解了文件加载内容,就是 java 文件经过编译后变成 .class 文件,类的各种信息就存储在 .class 文件中了,所以反射才能获取到类的各种信息。
java 代码编译为字节码的 .class 类文件,那 .class 文件里都有什么格式是什么?
class 文件结构采用类似 c 语言的结构体来存储数据。
CopyClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; }
它由 2 部分组成:无符号的数和表。所有的表都习惯以 _info
结尾。
无符号的数属于基本的数据类型,一 u1,u2,u4,u8 分别来表示 1 个字节,2 个字节,4 个字节和 8 个字节的无符号数,无符号数可以用来表示数字、索引引用、数量值。
表用于描述有层次关系的复合结构的数据,整个 class 文件本质就是一张表。
类的信息都存储在 .class 文件里,当把 .class 文件读入内存时,就会为之创建一个 Class 对象。
这里又涉及到虚拟机加载类的机制。周志明的《深入理解java虚拟机》里有一节讲类加载的内容,上面 class 文件结构也来自本书,可以好好看一看此书。
简单说:java 虚拟机把描述类的数据 class 文件加载到内存,并对数据进行效验、转换解析和初始化,最终形成可以被虚拟机直接使用的类型,这就是虚拟机的类加载机制。
在 java 语言里,类的加载和连接过程都是在程序运行期间完成的,虽然有性能开销,但是为 java 应用程序提供了高度的灵活性。比如反射就是发生在 java 运行时完成的。
在类加载阶段,虚拟机会在 java 堆中生成一个代表这个类的 java.lang.Class 对象,通过这个 Class 对象就可以访问到 jvm 中的这个类。
Class 类与 class 是不同,Class 是实实在在存在于 java.lang.Class 包中的一个类
反射:获取 Class 类对象及其类内部成员信息(属性, 方法, 构造函数等)以及控制实例对象的能力
四、反射功能常用的类
在 java 中,要使用反射功能,主要用到下面 2 个类:
java.lang.Class
java.lang.reflect
- java.lang.reflect.Constructor, 获取构造方法,Class 对象所表示类的构造方法
- Java.lang.reflect.Field, 字段成员,Class 对象所表示的类的成员变量,通过它可以动态修改成员变量值,包含 private
- Java.lang.reflect.Method,方法成员,Class 对象所表示的类的方法成员,通过它可以动态调用对象的方法
- Java.lang.reflect.Modifier,对类和成员访问修饰符进行解码