探索反射机制
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
publicfinalClassLoader?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)