探索反射机制
Spring,动态代理,都要用到反射的机制。
一个XXX.class 文件,首先这个文件,它会被Load 到内存里。
java程序的执行过程
ClassLoader将编译好的class 文件load 到内存中的codeSegment 代码段;运行环境找到main方法开始执行;运行过程中会有更多的class 被load 到内存(动态加载机制)
这里面一个一个class其实就是一个个对象,这个对象时什么对象呢?就是class那个类的对象。XXX.class
ClassLoader
ClassLoader是类装载器,用于将class装载进内存。
程序例子:TestDynamicLoading.java
(运行前,需要修改虚拟机参数) -verbose:lass,一个详尽的的输出过程,描述我们class的运行过程。
从上面输出可以看出以下问题:
ClassLoader加载类时候的动态加载机制:即需要时再加载
静态语句块static{} 只在类加载时执行一次
动态语句块{} 在每次实例化对象的时候都执行一次,类似于强行嵌入了构造函数中
JDK里面的ClassLoader 其实不只是一个,其实非常多的。
现在我们看一下我自己这个程序例子中的这个类,TestJDKClassLoader这个类被什么ClassLoaderLoad进来的。
ClassLoader的作用就是负责将类Load 到内存。所有的JRE 运行环境最核心的类,是bootstrap给Load进来的。bootstrap 一般是用C语言,或者汇编语言,等本地语言写的。
这个类,你动不了它。
举个例子,其实String 类,是JRE 里面,是比较核心的类了,是bootloader load 进来的。
最核心的ClassLoader 管理着,最核心的Class。
除了bootloader 其他的classLoader 都是用java写的。
这些classLoader 要想工作的话,其实也要被load 到内存。被谁load的,被bootloader。
PPT截图API
URLClassLoader
Load从网络上下载的类,也可以Load本地的,只是当做url路径来load。
JDK提供了N 多的classLoader这些只是比较常用的。
ClassLoader继承层次
所有的clasloader 除了bootClassLoader 其他的classLoader,都是从ClassLoader 继承。
下面说的classLoader 之间的“对象”之间的关系,不是类,是对象之间的关系。
其中有引用,不是继承。getParent()
getParent
publicfinal ClassLoaderᄃgetParent()
返回委托的父类加载器。
示例程序是: TestJDKClassLoader中分割线的下面,记住,不是继承。
是一个引用,但是这个引用,有什么用处呢?
探索JDK的深层次的类加载机制?
咱们自己的TestJDKClassLoader是被谁加载的,是
sun.misc.Launcher$AppClassLoader
那么它加载的过程是什么样子的,首先找它上一层的ClassLoader,sun.misc.Launcher$ExtClassLoader如果已经加载,它就不会再加载一遍了。
作用非常大。“自己写的java.lang.String,永远没机会执行。”
第四-反射
Class类
对于类装载器而言每个class文件就是一个Class对象;Class类事对于编译好的某一类对象的描述,描述了编译好的class文件的信息,是对类信息的描述,是类的metainfo(元信息)或者metadata(元数据),即描述数据的数据
ClassLoadergetClassLoader(),获得该类的类装载器
staticClass forName(String); 可根据类名加载相应的类,返回一个Class对象
ObjectnewInstance():实例化对象
其实从面向对象的高度看,类中的一个的属性也是一个对象,方法也是对象,即属性对象和方法对象
Method[] getMethods()
Class[] getParameterTypes()
Class m.getReturnType()
invoke(Object,Object... args)
Field[]getFields()
JDK里面提供了代表了,这些属性和方法 的类
反射
反射机制即指java可以在运行期间通过Class的ClassClass.forName(String)方法动态地加载一个类
继而可以通过获得的该类对应的的Class对象的ObjectnewInstance()方法实例化出该类的对象
然后可以通过Method[] getMethods() 和Field[]getFields()等方法了解类的内部结构
最后就可以根据方法的内部结构决定该方法应该怎么样去调用,从而动态地去调用类的方法m.invoke(Object,Object...args)