1.类的加载
在了解反射之前,先要了解一个类在内存中运行时,都经历了哪些事情。
会经历三个步骤:
加载:就是指将class文件读取到内存,并为之创建一个class对象;
连接:验证是否正确的内部结构。例如构造方法,基本属性等;准备为类的静态成员分配内存,并设置默认初始化值;将类的二进制数据中的符号引用替换为直接引用(例如int a = 1,在内存中,凡是用到a这个边的地方,都直接改为1,就没有a这个变量的存在)。
初始化:所有数据准备完毕,开始在内存中使用这个类。
如图所示。
如上图所示。Demo类要在内存中运行,首先会被编译成class字节码文件,然后通过JVM的加载器,将class字节码文件加载到方法区中,并为这个字节码文件在堆内存中创建一个字节码文件对象java.lang.class。将类中的静态成员放入放到方法区中的共享区,并设置初始值(基本数据类型默认是0,引用数据类型默认为null)。
2.类加载器的组成
1.bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责java核心类库的加载。(直白点就是java已经写好的类)
2.Extension ClassLoder 扩展类加载器
负责JRE的扩展目录jar包的加载。(直白点就是后期用到的那些jar包)
3.System ClassLoader 系统加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar和类路径。(直白说就是自己写的java类)
3.反射
思维引导:
思考一个问题:加入有一个手机类,这个手机类中有很多方法,属性,功能已经很完善了。但是随着科技的进步,现在又想往以前的手机里加功能,但是呢,又不能去动原来的手机,因为别人已经写好了,如果改动,将是毁灭性的灾难!
这时候,java就提供了一种技术:就是反射。反射就是在不改动源码的基础上,对以前的类进行方法的增强。我只需要你把你新添加的类的class文件交给我,我就可以通过反射技术来对以前的功能进行增强。(反射就好像是解剖一个标本,解剖完成后是不是就可以知道里面到底有什么。相对于java类而言,解剖完一个类之后,就可以直接使用这个类中的方法和属性)。
4.获取Class文件对象的三种方式
1.先获取这个的实例,在调用getClass()方法。(对象获取)
Person p = new Person();
Class c = p.getClass();
最终这个变量c就是Person这个类的全路径名,(class.com.xmcc.demo.person)
2.类名获取
Class c1 = Person.class
变量c1也是person类的全路径名。
3.Class类中的静态方法forName()获取
Class c2 = Class.forName("Person")
注意:这个方法会抛出一个ClassNotFoundException(类型找不到异常)。